bem-core icon indicating copy to clipboard operation
bem-core copied to clipboard

Use ES2015

Open veged opened this issue 8 years ago • 37 comments

We can autogenerate Modules-Wrapper from ES2015 syntax.

For simple cases (i.e. dom.js):

modules.define('dom', ['jquery'], function(provide, $) {
    provide({ /* ... */ });
});
import $ from 'bem:jquery'
export default { /* ... */ }

Same for elements.

For modifiers (i.e. button_type_link.js):

modules.define('button', function(provide, Button) {
    provide(Button.decl({ modName : 'type', modVal : 'link' }, { /* ... */ }));
});
import Button from 'bem:button'
export default Button.declMod({ modName : 'type', modVal : 'link' }, { /* ... */ })

Same for modifiers of elements.

For async provides (i.e. jquery.js)

modules.define(
    'jquery',
    ['loader__js', 'jquery__config'],
    function(provide, loader, cfg) {

function doProvide(preserveGlobal) {
    provide(preserveGlobal? jQuery : jQuery.noConflict(true));
}

typeof jQuery !== 'undefined'?
    doProvide(true) :
    loader(cfg.url, doProvide);
});
import provide from 'ym:provide'
import loader from 'bem:loader__js'
import cfg from 'bem:jquery__config'

doProvide = preserveGlobal => {
    provide(preserveGlobal? jQuery : jQuery.noConflict(true));
}

typeof jQuery !== 'undefined'?
    doProvide(true) :
    loader(cfg.url, doProvide);

Rollback

  • [ ] i-bem-dom__events_type_dom and i-bem-dom__events_type_bem <- i-bem-events, i-bem-events__dom and i-bem-events__bem
  • [ ] ua__dom <- page
  • [ ] jquery, loader_type_js

cc @narqo @dfilatov @aristov

veged avatar Jul 24 '15 14:07 veged

Just to be mentioned: we still need to think about this button_type_link vs loader_type_js case, as I'm not sure if loader_type_js is the only strange case we have. And still I don't like this camelcased 'EXPORT' ;)

narqo avatar Jul 24 '15 15:07 narqo

img_5744

dfilatov avatar Jul 24 '15 15:07 dfilatov

:+1:

awinogradov avatar Jul 24 '15 18:07 awinogradov

:fire:

voischev avatar Jul 25 '15 07:07 voischev

@veged does this issue introduce only syntactic sugar? Y-Modules will stay as a module system?

s-panferov avatar Jul 29 '15 13:07 s-panferov

@s-panferov YModules suppose to stay as compile target for Babel modules, cause we still have fully async modules (such as jQuery) — but for most of end users there is no need to know about YModules since they are fulfilled with ES2015 modules

veged avatar Jul 29 '15 13:07 veged

@veged will interop between the new modules and raw es6 modules be possible? E.g.:

npm install moment
import Button from 'button'
import moment from 'moment'
export Button.declMod({ modName : 'type', modVal : 'link' }, { /*
  use moment here: var now = moment()
*/ })

s-panferov avatar Jul 29 '15 13:07 s-panferov

@s-panferov short answer — no

npm install ... it's not about "raw ES6" modules, it's about npm/node.js modules system — https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import "module-name: The name of the module to import. This is a file name." — so treating module names is depends on "runtime", since for us main abstraction is BEM our modules reference to BEM-entities

for use npm-modules in our *.node.js files you still be able to use plain require('mymodule')

veged avatar Jul 29 '15 13:07 veged

@s-panferov ...but nothing coded yet, so we can think about details and change it later soon ;-)

veged avatar Jul 29 '15 16:07 veged

Don't see a single problem with using ES6 modules in *.node.js, if babel can transpile it to CJS modules, why we couldn't?

qfox avatar Jul 29 '15 21:07 qfox

@zxqfox there is a namespace problem — we have two different global spaces BEM and NPM, so you can't just use import mymodule from 'mymodule' and need to specify somehow from what modules namespace it should be used

we discussed about it and start to tend for something like import mymodule from 'bem:mymodule' for BEM modules and import mymodule from 'mymodule' for NPM modules

veged avatar Jul 30 '15 10:07 veged

@veged :+1: great!

qfox avatar Aug 02 '15 18:08 qfox

Current plan:

  1. Write an ENB plugin to assemble JS files in a way test-webpack-bem implementation assumes
  2. Write another ENB plugin to use WebPack API + Babel Loader + babel-plugin-bem

aristov avatar Sep 29 '15 11:09 aristov

The status:

  • https://github.com/bem/babel-plugin-bem
  • https://github.com/bem/enb-bem-babel
  • example usage: functions.vanilla.js

narqo avatar Oct 01 '15 16:10 narqo

https://github.com/bem/bem-core/blob/6b0e3496502475c88ec3b9ec111bcbed1d806b7e/common.blocks/functions/functions.vanilla.js#L21 why not () => {} ?

Guria avatar Oct 01 '15 17:10 Guria

@Guria i've already fixed that in 6cb6b5674ac876edb52e8c3ac809ade06b9fd116, but the main goal the task is still in progress.

narqo avatar Oct 01 '15 17:10 narqo

I've left some suggestions. Why not to start spec also? We risk to lose the logic with our evolutionary steps.

qfox avatar Oct 01 '15 18:10 qfox

@zxqfox what do you mean?

veged avatar Oct 02 '15 14:10 veged

@veged @zxqfox i beliave it's about issues in babel-plugin-bem repo.

narqo avatar Oct 02 '15 15:10 narqo

I have a some considerations about it:

  • Please, use ! as the delimeter instead of :, for example import $ from 'bem!jquery'. Most loaders from other world are using this convention, so it would be easy to combine with them.
  • Add at the file start some hint to help distinguish that this module has special behavior. Something like this: /* @yModule */.

just-boris avatar Nov 20 '15 17:11 just-boris

@just-boris

  • can you please provide examples about "most loaders"? maybe even some standardisation attempts?
  • for which modules /* @yModule */ needed? for every js file in {common,desktop,touch}.blocks/*/? looks a bit excessively :-/

veged avatar Dec 03 '15 10:12 veged

I just don't know more loaders.

just-boris avatar Dec 03 '15 11:12 just-boris

Well, /* @yModule */ declaration is redundant. Loader can hide all implementation details, and everything will be alright.

Also, regarding async provide. Since you have a special loader, you can place an export everywhere you want.

import loader from 'bem!loader__js';

loader('some-file.js', function(result) {
   export default result;
});

just-boris avatar Dec 03 '15 11:12 just-boris

@just-boris What about size of runtime? Did you compared it?

There is a talk on russian about loader__js. Please read it again. http://habrahabr.ru/post/213627/#comment_7352647

And, as an example of strange theoretical and even pseudoscientific comparisons: http://hackhat.com/p/110/module-loader-webpack-vs-requirejs-vs-browserify/ — Webpack won, so we should use it, right?

qfox avatar Dec 03 '15 11:12 qfox

@zxqfox I don't get what size should be compared here.

I just proposed to use ! notation to be more similar to other tools. What's wrong with it?

just-boris avatar Dec 03 '15 11:12 just-boris

Just read the answer is not enough, right?

require("!style!css!less!bootstrap/less/bootstrap.less");
// => the file "bootstrap.less" in the folder "less" in the "bootstrap"
//    module (that is installed from github to "node_modules") is
//    transformed by the "less-loader". The result is transformed by the
//    "css-loader" and then by the "style-loader".

I'll be waiting for the day when webpack will cook me a borscht!

var borscht = require('!smetaner!spetsier!salter!sugarer|potatoer!beeter!meater!water.js');

qfox avatar Dec 03 '15 11:12 qfox

You may not use long chain of loaders if you don't need it. Also here we are talking about other tools at all.

You can achieve the same hell as well with colon :. But ! is widely treated as splitter between module name and its loader. Even Webstorm recognizes it and resolves filenames followed after !.

just-boris avatar Dec 03 '15 11:12 just-boris

@just-boris Sure. But there is a HUGE difference between LOADERS and NAMESPACES. The first ones are functions.

Yes, we won't overuse these !, but users will. And then we should support these projects. You just don't know this progression and how it affect overall productivity.

I'm not against webpack, but when I see in their official docs how to load and transpile styles into js, I'm asking myself: are they mentally healthy? Is this a module loader or what? And you know, I don't like that feel.

qfox avatar Dec 03 '15 12:12 qfox

Colon-separated namespace reminds me about XSLT. Why you want mix it up with ES2015?

just-boris avatar Dec 03 '15 12:12 just-boris

placing export anywhere will be against ES2015 standard

veged avatar Dec 03 '15 12:12 veged