bem / bem-core

BEM Core Library
https://ru.bem.info/technologies/classic/i-bem/
Other
275 stars 94 forks source link

Use ES2015 #1109

Open veged opened 9 years ago

veged commented 9 years ago

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

cc @narqo @dfilatov @aristov

narqo commented 9 years ago

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' ;)

dfilatov commented 9 years ago

img_5744

awinogradov commented 9 years ago

:+1:

voischev commented 9 years ago

:fire:

s-panferov commented 9 years ago

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

veged commented 9 years ago

@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

s-panferov commented 9 years ago

@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()
*/ })
veged commented 9 years ago

@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 commented 9 years ago

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

qfox commented 9 years ago

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?

veged commented 9 years ago

@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

qfox commented 9 years ago

@veged :+1: great!

aristov commented 8 years ago

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
narqo commented 8 years ago

The status:

Guria commented 8 years ago

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

narqo commented 8 years ago

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

qfox commented 8 years ago

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

veged commented 8 years ago

@zxqfox what do you mean?

narqo commented 8 years ago

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

just-boris commented 8 years ago

I have a some considerations about it:

veged commented 8 years ago

@just-boris

just-boris commented 8 years ago

I just don't know more loaders.

just-boris commented 8 years ago

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;
});
qfox commented 8 years ago

@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?

just-boris commented 8 years ago

@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?

qfox commented 8 years ago

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');
just-boris commented 8 years ago

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 !.

qfox commented 8 years ago

@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.

just-boris commented 8 years ago

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

veged commented 8 years ago

placing export anywhere will be against ES2015 standard

s-panferov commented 8 years ago

@zxqfox webpack is not a module loader, it's a module bundler. The idea is to bundle everything inside your program and then use just one file or split it into chunks and load them on-demand. This is extremely powerful and simple conception and it boosts dev cycle a lot. The idea of loaders is powerful to, because it allows to add all types of files into your bundle and pipe transformations. Unix-way, you know.

Also, webpack offers alternatives for the simple inline-everyting strategy, e.g. extract-text-webpack-plugin, which allows you to extract your styles into a separate file or files.

maybe even some standardisation attempts?

Please see https://github.com/systemjs/systemjs/blob/master/docs/overview.md#plugin-loaders

qfox commented 8 years ago

@s-panferov I'm sorry that I called webpack a module loader when it's bundler. What a miss.

@just-boris How do you feel when you reading texts with colons? ;-) There are many cases, like: colon before definition, colon before list, colon before explanation.

Why you asking about XSLT? I hope it's not a birth trauma. But we need some delimiter. You proposing exclamation sign as already used in JS syntax for webpack. But. We talking about ES6 syntax and ES6 standard doesn't know anything about loaders for modules (it means webpack modules can't be converted as is into ES6 modules), it just expects that all modules will be somehow accessible. And since browsers doesn't have this functionality atm, we should make this runtime by self or use webpack. But once again, it's not a loader, it's a namespace.

just-boris commented 8 years ago

@veged ok, let's discuss it later.

Now the question is: why are you prefer bem:module rather than well-known bem!module? I don't say about loader semantics and details of implementation, just noted that a lot of developers and tools (text editors) are familiar with that notation and know what it means.

veged commented 8 years ago

@just-boris as I can see in brief loader bem!module is not the same as "namespace" bem:module, so developers and tools may be confused by difference — but we discuss it deeply with @dfilatov and @narqo, thanks for add more connections with existing things

qfox commented 8 years ago

Prbbly I'm wrong, but I see another syntax: https://github.com/WorldMaker/system-jade-virtualdom

import view from 'views/loading.jade!jade-vd' // (webpack) vs
import loader from 'bem!loader__js'; // (require.js) vs
import loader from 'bem:loader__js'; // our suggestion

The second one is the worst one at my pov. While the first one is like modifier or some kind of filter to me.

upd: This is okay to write import loader from 'bem:borstch.js!so-smetanoi';

upd2: There could be a crazy alternative: import loaderSoSmetanoj from 'bem/loader__js!smetanka';. Or even b_/blockname.

just-boris commented 8 years ago

@zxqfox are you loading borstch? So, here should be:

import loader from 'so-smetanoi!bem!borstch.js';
qfox commented 8 years ago

@just-boris Dude, look at the link please. https://github.com/WorldMaker/system-jade-virtualdom