diff --git a/package.json b/package.json index b34b290c..e2f44bcd 100644 --- a/package.json +++ b/package.json @@ -21,12 +21,21 @@ "bem-components": "^6.0.1", "bem-core": "^4.2.1", "bem-tools-create": "^2.1.0", + "bemdecl-to-fs-loader": "bempack/bemdecl-to-fs-loader#yeti-or.bempack", + "bemhtml-loader": "^0.0.1", + "bemjson-loader": "bempack/bemjson-loader#yeti-or.bempack", + "bh": "^4.1.3", + "bh-loader": "^0.0.1", + "css-loader": "^0.23.0", + "deps-loader": "bempack/deps-loader#yeti-or.bempack", "enb": "^1.3.0", "enb-bem-techs": "^2.2.1", "enb-bemxjst": "^8.6.7", "enb-borschik": "^3.0.0", "enb-js": "^1.1.0", "enb-postcss": "^2.0.0", + "extract-text-webpack-plugin": "^2.1.2", + "file-loader": "^0.8.5", "gulp": "gulpjs/gulp#4.0", "gulp-bem-bundle-builder": "^0.1.0", "gulp-bem-bundler-fs": "^0.0.10", @@ -43,13 +52,18 @@ "postcss-each": "^0.10.0", "postcss-for": "^2.1.1", "postcss-import": "^10.0.0", + "postcss-loader": "^0.8.2", "postcss-nested": "^2.0.2", "postcss-reporter": "^4.0.0", "postcss-simple-vars": "^4.0.0", "postcss-url": "^7.0.0", "rebem-css": "^0.2.0", + "style-loader": "^0.13.0", "through2-filter": "^2.0.0", - "ym": "^0.1.2" + "url-loader": "^0.5.7", + "webpack": "^2.7.0", + "ym": "^0.1.2", + "ymodules-loader": "^1.0.2" }, "scripts": { "test": "enb make && enb make clean && gulp", diff --git a/webpack.config.js b/webpack.config.js new file mode 100644 index 00000000..a4948f2d --- /dev/null +++ b/webpack.config.js @@ -0,0 +1,112 @@ +const BHRenderPlugin = require('./webpack/plugins/bh-render-plugin'); +const ExtractTextPlugin = require('extract-text-webpack-plugin'); +const path = require('path'); + +const levels = [ + 'node_modules/bem-core/common.blocks', + 'node_modules/bem-core/desktop.blocks', + 'node_modules/bem-components/common.blocks', + 'node_modules/bem-components/desktop.blocks', + 'node_modules/bem-components/design/common.blocks', + 'node_modules/bem-components/design/desktop.blocks', + 'common.blocks', + 'desktop.blocks' +]; +const extensions = [ + 'bh.js', + 'js', + 'vanilla.js', + 'css' +]; + +module.exports = { + entry: { + index: './desktop.bundles/index/index.bemjson.js' + }, + + output: { + path: path.join(__dirname, 'desktop.bundles/index'), + pathinfo: true, + filename: '[name].min.js' + }, + + module: { + rules: [ + { + test: /\.js/, + use: 'ymodules-loader' + }, + { + test: /\.bemjson.js$/, + use: [ + { + loader: 'bemdecl-to-fs-loader', + options: { + extensions: extensions, + levels: levels + } + }, + { + loader: 'deps-loader', + options: { + extensions: extensions, + levels: levels + } + }, + 'bemjson-loader' + ] + }, + { + test: /\.bh(\.js)?$/, + use: 'bh-loader' + }, + + { + test: /\.css$/, + use: ExtractTextPlugin.extract({ + fallback: "style-loader", + use: [ + { + loader: 'css-loader', + options: { + importLoaders: 1, + }, + }, + { + loader: 'postcss-loader', + options: { + plugins: [ + require('autoprefixer'), + require('postcss-import'), + require('postcss-each'), + require('postcss-for'), + require('postcss-simple-vars'), + require('postcss-calc'), + require('postcss-nested'), + require('rebem-css'), + require('postcss-url'), + ] + } + }, + ], + publicPath: 'desktop.bundles/index' + }) + }, + + { + test: /\.(gif|png|svg)$/, + use: 'url-loader' + } + ] + }, + + + devtool: 'source-map', + + plugins: [ + new BHRenderPlugin('index.html'), + new ExtractTextPlugin({ + filename: 'index.min.css' + }) + ] +}; diff --git a/webpack/plugins/bh-render-plugin.js b/webpack/plugins/bh-render-plugin.js new file mode 100644 index 00000000..66316a71 --- /dev/null +++ b/webpack/plugins/bh-render-plugin.js @@ -0,0 +1,57 @@ +var BH = require('bh').BH; +var path = require('path'); + +/** + * @param {string} filename + */ +function BHRenderPlugin(filename) { + this._filename = filename; +} + +BHRenderPlugin.prototype.apply = function (compiler) { + var filename = this._filename; + var resources = []; + + compiler.plugin('compilation', function (compilation, callback) { + compilation.plugin('normal-module-loader', function (loaderContext, module) { + if (module) { + if (/\.bh\.js$/i.test(module.resource)) { + resources.push(module.resource); + } + } else { + if (/\.bh\.js$/i.test(loaderContext.resource)) { + resources.push(loaderContext.resource); + } + } + }); + }); + + compiler.plugin('emit', function (compilation, callback) { + var bh = new BH(); + + bh.setOptions({ + jsAttrName: 'data-bem', + jsAttrScheme: 'json' + }); + + resources.forEach(file => { + require(file)(bh); + }); + + var bemjson = require(path.resolve(compiler.options.context, compiler.options.entry.index)); + var html = bh.apply(bemjson); + + compilation.assets[filename] = { + source: function () { + return html; + }, + size: function () { + return html.length; + }, + }; + + callback(); + }); +}; + +module.exports = BHRenderPlugin;