From 0189d7d29a03eb5310d3978703d48f4253dde7d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Se=CC=81rgio=20Ramos?= Date: Mon, 5 Dec 2016 20:11:55 +0000 Subject: [PATCH] re-organize webpack configuration - detach plugins configuration - use aliases - add project root to frontend module resolver --- frontend/webpack/base.js | 83 ++++++++++---------------- frontend/webpack/development.js | 19 +++--- frontend/webpack/plugins.js | 45 ++++++++++++++ frontend/webpack/production.js | 20 ++++--- frontend/webpack/test.js | 8 +-- ui/webpack/base.js | 102 ++++++++------------------------ ui/webpack/development.js | 61 ++++++++++++++----- ui/webpack/plugins.js | 62 +++++++++++++++++++ ui/webpack/production.js | 51 ++++++++++------ ui/webpack/test.js | 6 +- 10 files changed, 273 insertions(+), 184 deletions(-) create mode 100644 frontend/webpack/plugins.js create mode 100644 ui/webpack/plugins.js diff --git a/frontend/webpack/base.js b/frontend/webpack/base.js index 22c57dd7..0b99831c 100644 --- a/frontend/webpack/base.js +++ b/frontend/webpack/base.js @@ -1,72 +1,55 @@ const ExtractTextPlugin = require('extract-text-webpack-plugin'); -const pkg = require('../package.json'); -const webpack = require('webpack'); -const WebpackShellPlugin = require('webpack-shell-plugin'); const path = require('path'); +const fs = require('fs'); -const plugins = { - 'no-errors-plugin': new webpack.NoErrorsPlugin(), - 'extract-text-plugin': new ExtractTextPlugin({ - filename: 'bundle.css', - allChunks: true - }), - 'loader-options-plugin': new webpack.LoaderOptionsPlugin({ - options: { - postcss: { - plugins: [ - require('postcss-modules-values'), - require('postcss-cssnext')() - ] - } - } - }), - 'define-plugin': new webpack.DefinePlugin({ - 'process.env': { - NODE_ENV: JSON.stringify(process.env.NODE_ENV || 'development'), - APP_NAME: JSON.stringify(pkg.name), - APP_VERSION: JSON.stringify(pkg.version) - } - }), - 'shell-plugin': new WebpackShellPlugin({ - onBuildStart: ['npm run build-locales'] - }) -}; +const plugins = require('./plugins'); +const CONTEXT = path.join(__dirname, '../src'); +const STATIC = path.join(__dirname, '../static'); +const ROOT = path.join(__dirname, '../..'); -exports.config = { - context: path.join(__dirname, '../src'), +module.exports = { + context: CONTEXT, + resolve: { + modules: [ + ROOT, + 'node_modules' + ], + alias: fs.readdirSync(CONTEXT) + .map((name) => path.join(CONTEXT, name)) + .filter((fullpath) => fs.statSync(fullpath).isDirectory()) + .reduce((aliases, fullpath) => Object.assign(aliases, { + [`@${path.basename(fullpath)}`]: fullpath + }), { + '@root': CONTEXT + }) + }, output: { - path: path.join(__dirname, '../static'), + path: STATIC, publicPath: '/static/', filename: 'bundle.js' }, plugins: [ - plugins['no-errors-plugin'], - plugins['extract-text-plugin'], - plugins['loader-options-plugin'], - plugins['define-plugin'], - plugins['shell-plugin'] + plugins['no-errors'], + plugins['extract-text'], + plugins['loader-options'], + plugins['define'], + plugins['shell'] ], module: { loaders: [{ test: /js?$/, exclude: /node_modules/, - include: [ - path.join(__dirname, '../src') - ], - loaders: ['babel'] + include: [CONTEXT], + loaders: ['babel-loader'] }, { test: /\.json?$/, exclude: /node_modules/, - include: [ - path.join(__dirname, '../src') - ], - loaders: ['json'] + include: [CONTEXT], + loaders: ['json-loader'] }, { test: /\.css?$/, exclude: /node_modules/, - include: [ - path.join(__dirname, '../src') - ], + include: [CONTEXT], loader: ExtractTextPlugin.extract({ fallbackLoader: 'style-loader', loader: [ @@ -79,5 +62,3 @@ exports.config = { }] } }; - -exports.plugins = plugins; diff --git a/frontend/webpack/development.js b/frontend/webpack/development.js index fa85d998..2ab2ac5b 100644 --- a/frontend/webpack/development.js +++ b/frontend/webpack/development.js @@ -1,30 +1,31 @@ -const graphql = require('../../cloudapi-graphql/src/endpoint'); -const base = require('./base.js'); -const webpack = require('webpack'); +// const graphql = require('../../cloudapi-graphql/src/endpoint'); +const plugins = require('./plugins'); +const base = require('./base'); const devServer = { hot: true, compress: true, lazy: false, - publicPath: base.config.output.publicPath, + publicPath: base.output.publicPath, setup: (app) => { - app.use('/graphql', graphql); + // app.use('/graphql', graphql); }, historyApiFallback: { index: './static/index.html' } }; -module.exports = Object.assign(base.config, { +module.exports = Object.assign(base, { + devtool: 'eval-source-map', entry: [ 'react-hot-loader/patch', 'webpack-dev-server/client?http://localhost:8080', 'webpack/hot/only-dev-server', './index.js' ], - plugins: base.config.plugins.concat([ - new webpack.HotModuleReplacementPlugin() + plugins: base.plugins.concat([ + plugins['named-modules'], + plugins['hot-module-replacement'] ]), - devtool: 'source-map', devServer }); diff --git a/frontend/webpack/plugins.js b/frontend/webpack/plugins.js new file mode 100644 index 00000000..3fac23db --- /dev/null +++ b/frontend/webpack/plugins.js @@ -0,0 +1,45 @@ +const ExtractTextPlugin = require('extract-text-webpack-plugin'); +const pkg = require('../package.json'); +const webpack = require('webpack'); +const WebpackShellPlugin = require('webpack-shell-plugin'); + +module.exports = { + 'no-errors': new webpack.NoErrorsPlugin(), + 'occurrence-order': new webpack.optimize.OccurrenceOrderPlugin(true), + 'aggressive-merging': new webpack.optimize.AggressiveMergingPlugin(), + 'hot-module-replacement': new webpack.HotModuleReplacementPlugin(), + 'named-modules': new webpack.NamedModulesPlugin(), + 'extract-text': new ExtractTextPlugin({ + filename: 'bundle.css', + allChunks: true + }), + 'loader-options': new webpack.LoaderOptionsPlugin({ + options: { + postcss: { + plugins: [ + require('postcss-modules-values'), + require('postcss-cssnext')() + ] + } + } + }), + 'define': new webpack.DefinePlugin({ + 'process.env': { + NODE_ENV: JSON.stringify(process.env.NODE_ENV || 'development'), + APP_NAME: JSON.stringify(pkg.name), + APP_VERSION: JSON.stringify(pkg.version) + } + }), + 'shell': new WebpackShellPlugin({ + onBuildStart: ['npm run build-locales'] + }), + 'uglify-js': new webpack.optimize.UglifyJsPlugin({ + sourceMap: true, + mangle: true, + output: { + comments: false, + indent_level: 2 + } + }) +}; + diff --git a/frontend/webpack/production.js b/frontend/webpack/production.js index 94a94ff3..473f9238 100644 --- a/frontend/webpack/production.js +++ b/frontend/webpack/production.js @@ -1,16 +1,18 @@ -const base = require('./base.js'); -const webpack = require('webpack'); +const plugins = require('./plugins'); +const base = require('./base'); -module.exports = Object.assign(base.config, { + +module.exports = Object.assign(base, { + devtool: 'hidden-source-map', entry: [ './index.js' ], - plugins: base.config.plugins.concat([ - new webpack.optimize.DedupePlugin(), - new webpack.optimize.OccurrenceOrderPlugin(true), - new webpack.optimize.UglifyJsPlugin() - ]), - devtool: 'eval' + plugins: base.plugins.concat([ + plugins['named-modules'] + // plugins['occurrence-order'], + // plugins['aggressive-merging'], + // plugins['uglify-js'] + ]) }); /* diff --git a/frontend/webpack/test.js b/frontend/webpack/test.js index f7ff55c5..dc21c9d1 100644 --- a/frontend/webpack/test.js +++ b/frontend/webpack/test.js @@ -1,13 +1,13 @@ -const base = require('./base'); +const plugins = require('./plugins'); module.exports = { output: { libraryTarget: 'commonjs2' }, plugins: [ - base.plugins['no-errors-plugin'], - base.plugins['loader-options-plugin'], - base.plugins['define-plugin'] + plugins['no-errors-plugin'], + plugins['loader-options-plugin'], + plugins['define-plugin'] ], module: { loaders: [{ diff --git a/ui/webpack/base.js b/ui/webpack/base.js index a74fda25..cb8b3040 100644 --- a/ui/webpack/base.js +++ b/ui/webpack/base.js @@ -1,98 +1,48 @@ -const ExtractTextPlugin = require('extract-text-webpack-plugin'); -const webpack = require('webpack'); +const gracefulFs = require('graceful-fs'); const path = require('path'); -const cssFunctions = require('../src/shared/functions'); +const fs = require('fs'); -const plugins = { - 'no-errors-plugin': new webpack.NoErrorsPlugin(), - 'extract-text-plugin': new ExtractTextPlugin({ - filename: 'css/[name].css', - allChunks: true - }), - 'loader-options-plugin': new webpack.LoaderOptionsPlugin({ - options: { - postcss: { - plugins: [ - require('postcss-import')(), - require('postcss-constants')({}), - require('postcss-at-rules-variables')(), - require('postcss-functions')({ - functions: cssFunctions - }), - require('postcss-mixins')({ - mixinsFiles: path.join(__dirname, '../src/shared/mixins.css') - }), - require('postcss-for'), - require('postcss-cssnext')() - ] - }, - 'embed-markdown-loader': { - mode: 'plain' - } - } - }) -}; +const plugins = require('./plugins'); -exports.config = { - context: path.join(__dirname, '../'), +const CONTEXT = path.join(__dirname, '../'); +const STATIC = path.join(__dirname, '../static'); +const SRC = path.join(__dirname, '../src'); +const DOCS = path.join(__dirname, '../docs'); + +// PATCH `fs` to avoid ENFILE errors +gracefulFs.gracefulify(fs); + +module.exports = { + devtool: 'eval', + context: CONTEXT, + entry: path.join(SRC, 'index.js'), output: { - path: path.join(__dirname, '../static'), + path: STATIC, publicPath: '/', - filename: 'js/[name].js' + filename: '[name].js' }, plugins: [ - plugins['no-errors-plugin'], - plugins['extract-text-plugin'], - plugins['loader-options-plugin'] + plugins['no-errors'], + plugins['extract-text'], + plugins['loader-options'] ], - resolveLoader: { - alias: { - 'embed-markdown-loader': path.join(__dirname, './embed-markdown-loader') - } - }, module: { loaders: [{ test: /js?$/, exclude: /node_modules/, include: [ - path.join(__dirname, '../src'), - path.join(__dirname, '../docs') + SRC, + DOCS ], - loader: 'babel' + loader: 'babel-loader' }, { test: /\.json?$/, exclude: /node_modules/, include: [ - path.join(__dirname, '../src'), - path.join(__dirname, '../docs') + SRC, + DOCS ], - loader: 'json' - }, { - test: /\.md?$/, - exclude: /node_modules/, - include: [ - path.join(__dirname, '../src'), - path.join(__dirname, '../docs') - ], - loader: 'raw-loader!embed-markdown-loader' - }, { - test: /\.css?$/, - exclude: /node_modules/, - include: [ - path.join(__dirname, '../src'), - path.join(__dirname, '../docs') - ], - loader: ExtractTextPlugin.extract({ - fallbackLoader: 'style-loader', - loader: [ - 'css-loader?', - 'modules&importLoaders=1&', - 'localIdentName=[name]__[local]___[hash:base64:5]!', - 'postcss-loader' - ].join('') - }) + loader: 'json-loader' }] } }; - -exports.plugins = plugins; diff --git a/ui/webpack/development.js b/ui/webpack/development.js index 7f31e3d2..6a60301e 100644 --- a/ui/webpack/development.js +++ b/ui/webpack/development.js @@ -1,11 +1,16 @@ -const pkg = require('../package.json'); -const base = require('./base.js'); -const webpack = require('webpack'); +const ExtractTextPlugin = require('extract-text-webpack-plugin'); +const plugins = require('./plugins'); +const base = require('./base'); const path = require('path'); +const EmbedMarkdownLoader = path.join(__dirname, './embed-markdown-loader'); +const STATIC = path.join(__dirname, '../static'); +const SRC = path.join(__dirname, '../src'); +const DOCS = path.join(__dirname, '../docs'); + const devServer = { contentBase: [ - path.join(__dirname, '../static/') + STATIC ], hot: true, compress: true, @@ -15,7 +20,7 @@ const devServer = { } }; -module.exports = Object.assign(base.config, { +module.exports = Object.assign(base, { entry: { docs: [ 'react-hot-loader/patch', @@ -24,16 +29,42 @@ module.exports = Object.assign(base.config, { './docs/index.js' ] }, - plugins: base.config.plugins.concat([ - new webpack.HotModuleReplacementPlugin(), - new webpack.DefinePlugin({ - 'process.env': { - NODE_ENV: JSON.stringify(process.env.NODE_ENV || 'development'), - APP_NAME: JSON.stringify(pkg.name), - APP_VERSION: JSON.stringify(pkg.version) - } - }) + resolveLoader: { + alias: { + 'embed-markdown-loader': EmbedMarkdownLoader + } + }, + plugins: base.plugins.concat([ + plugins['named-modules'], + plugins['hot-module-replacement'], + plugins['define'] ]), - devtool: 'source-map', + module: Object.assign(base.module, { + loaders: base.module.loaders.concat([{ + test: /\.md?$/, + exclude: /node_modules/, + include: [ + SRC, + DOCS + ], + loader: 'raw-loader!embed-markdown-loader' + }, { + test: /\.css?$/, + exclude: /node_modules/, + include: [ + SRC, + DOCS + ], + loader: ExtractTextPlugin.extract({ + fallbackLoader: 'style-loader', + loader: [ + 'css-loader?', + 'modules&importLoaders=1&', + 'localIdentName=[name]__[local]___[hash:base64:5]!', + 'postcss-loader' + ].join('') + }) + }]) + }), devServer }); diff --git a/ui/webpack/plugins.js b/ui/webpack/plugins.js new file mode 100644 index 00000000..785a4ff9 --- /dev/null +++ b/ui/webpack/plugins.js @@ -0,0 +1,62 @@ +const WebpackShellPlugin = require('webpack-shell-plugin'); +const ExtractTextPlugin = require('extract-text-webpack-plugin'); +const webpack = require('webpack'); +const path = require('path'); + +const cssFunctions = require('../src/shared/functions'); +const mixins = path.join(__dirname, '../src/shared/mixins.css'); +const pkg = require('../package.json'); + +module.exports = { + 'occurrence-order': new webpack.optimize.OccurrenceOrderPlugin(true), + 'aggressive-merging': new webpack.optimize.AggressiveMergingPlugin(), + 'hot-module-replacement': new webpack.HotModuleReplacementPlugin(), + 'named-modules': new webpack.NamedModulesPlugin(), + 'no-errors': new webpack.NoErrorsPlugin(), + 'extract-text': new ExtractTextPlugin({ + filename: '[name].css', + allChunks: true + }), + 'loader-options': new webpack.LoaderOptionsPlugin({ + options: { + postcss: { + plugins: [ + require('postcss-import')(), + require('postcss-constants')({}), + require('postcss-at-rules-variables')(), + require('postcss-functions')({ + functions: cssFunctions + }), + require('postcss-mixins')({ + mixinsFiles: mixins + }), + require('postcss-for'), + require('postcss-cssnext')() + ] + }, + 'embed-markdown-loader': { + mode: 'plain' + } + } + }), + 'define': new webpack.DefinePlugin({ + 'process.env': { + NODE_ENV: JSON.stringify(process.env.NODE_ENV || 'development'), + APP_NAME: JSON.stringify(pkg.name), + APP_VERSION: JSON.stringify(pkg.version) + } + }), + 'uglify-js': new webpack.optimize.UglifyJsPlugin({ + sourceMap: true, + mangle: true, + output: { + comments: false, + indent_level: 2 + } + }), + 'shell': new WebpackShellPlugin({ + onBuildEnd: [ + 'npm run build-docs-static' + ] + }) +}; \ No newline at end of file diff --git a/ui/webpack/production.js b/ui/webpack/production.js index 788fee06..557302b9 100644 --- a/ui/webpack/production.js +++ b/ui/webpack/production.js @@ -1,25 +1,42 @@ -const WebpackShellPlugin = require('webpack-shell-plugin'); -const base = require('./base.js'); -const webpack = require('webpack'); -const entries = require('./entrypoints'); const path = require('path'); -module.exports = Object.assign(base.config, { - entry: entries.reduce((all, entry) => { - all[entry.name] = [`./${path.relative(base.config.context, entry.path)}`]; +const plugins = require('./plugins'); +const base = require('./base'); +const entries = require('./entrypoints'); + +const SRC = path.join(__dirname, '../src'); + +module.exports = Object.assign(base, { + output: Object.assign(base.output, { + libraryTarget: 'commonjs2' + }), + entry: entries.filter((entry) => { + return entry.name !== 'docs'; + }).reduce((all, entry) => { + all[entry.name] = [`./${path.relative(base.context, entry.path)}`]; return all; }, {}), - plugins: base.config.plugins.concat([ - new webpack.optimize.DedupePlugin(), - new webpack.optimize.OccurrenceOrderPlugin(true), - new webpack.optimize.UglifyJsPlugin(), - new WebpackShellPlugin({ - onBuildEnd: [ - 'npm run build-docs-static' - ] - }) + plugins: base.plugins.concat([ + plugins['occurrence-order'], + plugins['aggressive-merging'], + plugins['uglify-js'] ]), - devtool: 'eval' + module: Object.assign(base.module, { + loaders: base.module.loaders.concat([{ + test: /\.css?$/, + exclude: /node_modules/, + include: [ + SRC + ], + loader: [ + 'style-loader!', + 'css-loader?', + 'modules&importLoaders=1&', + 'localIdentName=[name]__[local]___[hash:base64:5]!', + 'postcss-loader' + ].join('') + }]) + }) }); /* diff --git a/ui/webpack/test.js b/ui/webpack/test.js index a4f6e954..557c100f 100644 --- a/ui/webpack/test.js +++ b/ui/webpack/test.js @@ -1,12 +1,12 @@ -const base = require('./base'); +const plugins = require('./plugins'); module.exports = { output: { libraryTarget: 'commonjs2' }, plugins: [ - base.plugins['no-errors-plugin'], - base.plugins['loader-options-plugin'] + plugins['no-errors'], + plugins['loader-options'] ], module: { loaders: [{