From 9bfe85097b16cfff3d625ffbdd657d528997f530 Mon Sep 17 00:00:00 2001 From: Grgur Grisogono Date: Mon, 14 Nov 2016 12:14:32 +0100 Subject: [PATCH 1/6] aggressive on --- webpack.config.js | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/webpack.config.js b/webpack.config.js index cbd935e..6e5dbb6 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -11,14 +11,10 @@ const staticsPath = path.join(__dirname, './static'); const extractCSS = new ExtractTextPlugin('style.css'); const plugins = [ - new webpack.optimize.CommonsChunkPlugin({ - name: 'vendor', - minChunks: Infinity, - filename: 'vendor.bundle.js' - }), new webpack.DefinePlugin({ 'process.env': { NODE_ENV: JSON.stringify(nodeEnv) } }), + new webpack.optimize.AggressiveSplittingPlugin(), ]; if (isProd) { @@ -51,21 +47,20 @@ if (isProd) { module.exports = { devtool: isProd ? 'source-map' : 'eval', context: sourcePath, + entry: { js: [ 'index', 'pages/Home' ], - vendor: [ - 'react', - 'react-dom' - ] }, + output: { path: staticsPath, - filename: 'bundle.js', + filename: '[id]-[chunkhash].js', publicPath: '/', }, + module: { rules: [ { @@ -102,6 +97,7 @@ module.exports = { } ], }, + resolve: { extensions: ['.js', '.jsx'], modules: [ @@ -109,7 +105,21 @@ module.exports = { 'node_modules' ] }, + plugins: plugins, + recordsOutputPath: path.join(__dirname, 'chunk.records.json'), + + stats: { + assets: true, + children: false, + hash: false, + modules: false, + publicPath: false, + timings: true, + version: false, + warnings: true + }, + devServer: { contentBase: './client', historyApiFallback: true, From ac2373a44ade89ba5aab7e90da3036059620b43a Mon Sep 17 00:00:00 2001 From: Grgur Grisogono Date: Mon, 14 Nov 2016 12:49:54 +0100 Subject: [PATCH 2/6] colors yay --- webpack.config.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/webpack.config.js b/webpack.config.js index 6e5dbb6..c9acc2f 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -117,7 +117,11 @@ module.exports = { publicPath: false, timings: true, version: false, - warnings: true + warnings: true, + colors: { + yellow: '\u001b[33m', + green: '\u001b[32m' + } }, devServer: { From c5b9238d13d6a2b9fc62c494c18d6438e93a5702 Mon Sep 17 00:00:00 2001 From: Grgur Grisogono Date: Mon, 14 Nov 2016 13:39:31 +0100 Subject: [PATCH 3/6] webpack bump to beta 26 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8816d81..6655878 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "node-sass": "^3.12.2", "sass-loader": "^4", "style-loader": "^0.13.1", - "webpack": "^2.1.0-beta.4", + "webpack": "^2.1.0-beta.26", "webpack-dev-server": "^2.1.0-beta.10" }, "dependencies": { From 6aa1f1c0b7a9c94f88c2fe43629474a9e13bd19d Mon Sep 17 00:00:00 2001 From: Grgur Grisogono Date: Mon, 14 Nov 2016 13:39:43 +0100 Subject: [PATCH 4/6] dont care for extract text now --- client/index.html | 1 - webpack.config.js | 24 ++++++++++++------------ 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/client/index.html b/client/index.html index 13f5b8a..56c3d57 100644 --- a/client/index.html +++ b/client/index.html @@ -4,7 +4,6 @@ React Router + Webpack 2 + Dynamic Chunk Navigation -
diff --git a/webpack.config.js b/webpack.config.js index 4a1f8dc..26ccfa5 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,6 +1,5 @@ const webpack = require('webpack'); const path = require('path'); -const ExtractTextPlugin = require('extract-text-webpack-plugin'); const nodeEnv = process.env.NODE_ENV || 'development'; const isProd = nodeEnv === 'production'; @@ -8,12 +7,19 @@ const isProd = nodeEnv === 'production'; const sourcePath = path.join(__dirname, './client'); const staticsPath = path.join(__dirname, './static'); -const extractCSS = new ExtractTextPlugin('style.css'); - const plugins = [ new webpack.DefinePlugin({ 'process.env': { NODE_ENV: JSON.stringify(nodeEnv) } }), + new webpack.LoaderOptionsPlugin({ + options: { + context: sourcePath, + sassLoader: { + outputStyle: 'expanded', + includePaths: [sourcePath], + }, + }, + }), new webpack.optimize.AggressiveSplittingPlugin(), ]; @@ -39,8 +45,7 @@ if (isProd) { output: { comments: false }, - }), - extractCSS + }) ); } @@ -72,12 +77,7 @@ module.exports = { }, { test: /\.scss$/, - use: isProd ? - extractCSS.extract({ - fallbackLoader: 'style-loader', - loader: ['css-loader', 'sass-loader'], - }) : - ['style-loader', 'css-loader', 'sass-loader'] + use: ['style-loader', 'css-loader', 'sass-loader'] }, { test: /\.(js|jsx)$/, @@ -99,7 +99,7 @@ module.exports = { }, resolve: { - extensions: ['.js', '.jsx'], + extensions: ['.js', '.jsx', '.scss'], modules: [ sourcePath, 'node_modules' From 3e9e658c27196cb3496c775f12930e3b3c9207f7 Mon Sep 17 00:00:00 2001 From: Grgur Grisogono Date: Tue, 15 Nov 2016 18:47:42 +0100 Subject: [PATCH 5/6] attempt to inject entry points to html (dont do this at home) --- InitialChunksPlugin.js | 126 +++++++++++++++++++++++++++++++++++++++++ client/index.html | 2 - client/index.js | 3 + webpack.config.js | 2 + 4 files changed, 131 insertions(+), 2 deletions(-) create mode 100644 InitialChunksPlugin.js diff --git a/InitialChunksPlugin.js b/InitialChunksPlugin.js new file mode 100644 index 0000000..fde0d18 --- /dev/null +++ b/InitialChunksPlugin.js @@ -0,0 +1,126 @@ +/* eslint-disable no-var,strict,vars-on-top */ +'use strict'; +var Promise = require('bluebird'); +var fs = Promise.promisifyAll(require('fs')); +var _ = require('lodash'); +var path = require('path'); + +function InitialChunksPlugin(options) { + // Default options + this.options = _.extend({ + publicPath: './static' + }, options); +} + +InitialChunksPlugin.prototype.apply = function(compiler) { + var self = this; + + compiler.plugin('after-emit', function(compilation, callback) { + var stats = compilation.getStats().toJson(); + var entrypoints = stats.entrypoints.js.assets || []; + + // console.log('stats', Object.keys(stats)); + // console.log('stats', stats.chunks); + + var htmlAsset = stats.assets.find(function(asset) { + return asset.name.match(/[.]html?$/); + }); + + if (!htmlAsset) { + return callback(); + } + + var htmlFile = htmlAsset.name; + var filename = path.resolve(compilation.compiler.context, self.options.publicPath, htmlFile); + + if (self.isHotUpdateCompilation(entrypoints)) { + return callback(); + } + + var tags = self.createTags(entrypoints); + + // If the template and the assets did not change we don't have to emit the html + var assetJson = JSON.stringify(entrypoints); + if (self.options.cache && assetJson === self.assetJson) { + return callback(); + } + + self.assetJson = assetJson; + + return Promise.props({ + size: fs.statAsync(filename), + source: fs.readFileAsync(filename, 'utf-8') + }) + .catch(function() { + return Promise.reject(new Error('HtmlWebpackPlugin: could not load file ' + filename)); + }) + .then(function(results) { + return fs.writeFileAsync(filename, self.injectAssetsIntoHtml(results.source, tags)); + }). + finally(function() { + callback(); + }); + }); +}; + + +InitialChunksPlugin.prototype.isHotUpdateCompilation = function(assets) { + return assets.length && assets.every(function(name) { + return /\.hot-update\.js$/.test(name); + }); +}; + +/** + * Turn a tag definition into a html string + */ +InitialChunksPlugin.prototype.createTags = function(assets) { + var tags = this.generateAssetTags(assets); + return tags.map(function(tagDefinition) { + var attributes = Object.keys(tagDefinition.attributes || {}).map(function(attributeName) { + return attributeName + '="' + tagDefinition.attributes[attributeName] + '"'; + }); + return '<' + [tagDefinition.tagName].concat(attributes).join(' ') + (tagDefinition.selfClosingTag ? '/' : '') + '>' + + (tagDefinition.innerHTML || '') + + (tagDefinition.closeTag ? '' : ''); + }); +}; + +/** + * Injects the assets into the given html string + */ +InitialChunksPlugin.prototype.generateAssetTags = function(assets) { + // Turn script files into script tags + return assets.map(function(scriptPath) { + return { + tagName: 'script', + closeTag: true, + attributes: { + type: 'text/javascript', + src: scriptPath + } + }; + }); +}; + +/** + * Injects the assets into the given html string + */ +InitialChunksPlugin.prototype.injectAssetsIntoHtml = function(html, assetTags) { + var bodyRegExp = /(<\/body>)/i; + + if (assetTags.length) { + if (bodyRegExp.test(html)) { + // Append assets to body element + html = html.replace(bodyRegExp, function(match) { + return assetTags + match; + }); + } else { + // Append scripts to the end of the file if no element exists: + html += assetTags; + } + } + + return html; +}; + +module.exports = InitialChunksPlugin; diff --git a/client/index.html b/client/index.html index 56c3d57..8ef08d7 100644 --- a/client/index.html +++ b/client/index.html @@ -7,7 +7,5 @@
- - diff --git a/client/index.js b/client/index.js index 2b5b250..c28aabe 100644 --- a/client/index.js +++ b/client/index.js @@ -5,6 +5,9 @@ import rootRoute from 'pages/routes'; import 'index.html'; import 'general.scss'; +console.log('STARTING'); +window.foo = '123'; + render( , document.getElementById('root') diff --git a/webpack.config.js b/webpack.config.js index 26ccfa5..56bdfdf 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,5 +1,6 @@ const webpack = require('webpack'); const path = require('path'); +const InitialChunksPlugin = require('./InitialChunksPlugin'); const nodeEnv = process.env.NODE_ENV || 'development'; const isProd = nodeEnv === 'production'; @@ -21,6 +22,7 @@ const plugins = [ }, }), new webpack.optimize.AggressiveSplittingPlugin(), + new InitialChunksPlugin({ publicPath: staticsPath, }), ]; if (isProd) { From d233338d8aef1151b42adacaab0184ddd181549b Mon Sep 17 00:00:00 2001 From: Grgur Grisogono Date: Mon, 23 Jan 2017 12:24:27 +0100 Subject: [PATCH 6/6] webpack 2.2 compatible but still not working --- InitialChunksPlugin.js | 7 +++---- package.json | 34 +++++++++++++++++----------------- webpack.config.js | 11 ++++++----- 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/InitialChunksPlugin.js b/InitialChunksPlugin.js index fde0d18..4dd62c4 100644 --- a/InitialChunksPlugin.js +++ b/InitialChunksPlugin.js @@ -19,13 +19,12 @@ InitialChunksPlugin.prototype.apply = function(compiler) { var stats = compilation.getStats().toJson(); var entrypoints = stats.entrypoints.js.assets || []; - // console.log('stats', Object.keys(stats)); - // console.log('stats', stats.chunks); - var htmlAsset = stats.assets.find(function(asset) { return asset.name.match(/[.]html?$/); }); + console.log('entrypoints', entrypoints); + if (!htmlAsset) { return callback(); } @@ -52,7 +51,7 @@ InitialChunksPlugin.prototype.apply = function(compiler) { source: fs.readFileAsync(filename, 'utf-8') }) .catch(function() { - return Promise.reject(new Error('HtmlWebpackPlugin: could not load file ' + filename)); + return Promise.reject(new Error('InitialChunksPlugin: could not load file ' + filename)); }) .then(function(results) { return fs.writeFileAsync(filename, self.injectAssetsIntoHtml(results.source, tags)); diff --git a/package.json b/package.json index 6655878..618a110 100644 --- a/package.json +++ b/package.json @@ -12,25 +12,25 @@ }, "license": "MIT", "devDependencies": { - "babel-core": "^6.16.0", - "babel-loader": "^6.2.7", - "babel-plugin-transform-runtime": "^6.15.0", - "babel-preset-es2015": "^6.18.0", - "babel-preset-react": "^6.15.0", + "babel-core": "6.16.0", + "babel-loader": "6.2.7", + "babel-plugin-transform-runtime": "6.15.0", + "babel-preset-es2015": "6.18.0", + "babel-preset-react": "6.22.0", "css-loader": "0.14.5", - "extract-text-webpack-plugin": "^2.0.0-beta.4", - "file-loader": "^0.8.5", - "node-sass": "^3.12.2", - "sass-loader": "^4", - "style-loader": "^0.13.1", - "webpack": "^2.1.0-beta.26", - "webpack-dev-server": "^2.1.0-beta.10" + "extract-text-webpack-plugin": "2.0.0-beta.5", + "file-loader": "0.8.5", + "html-webpack-plugin": "2.26.0", + "node-sass": "3.12.2", + "sass-loader": "3.2.3", + "style-loader": "0.13.1", + "webpack": "2.2.0", + "webpack-dev-server": "2.2.0" }, "dependencies": { - "babel-polyfill": "^6.16.0", - "babel-runtime": "^6.16.0", - "react": "^15.3.0", - "react-dom": "^15.3.0", - "react-router": "^2.8.0" + "babel-runtime": "6.22.0", + "react": "15.4.2", + "react-dom": "15.4.2", + "react-router": "2.8.0" } } diff --git a/webpack.config.js b/webpack.config.js index 56bdfdf..4119ef6 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -72,10 +72,12 @@ module.exports = { rules: [ { test: /\.html$/, - use: 'file-loader', - query: { - name: '[name].[ext]' - } + use: { + loader: 'file-loader', + query: { + name: '[name].[ext]' + }, + }, }, { test: /\.scss$/, @@ -129,7 +131,6 @@ module.exports = { devServer: { contentBase: './client', historyApiFallback: true, - inject: true, port: 3000, compress: isProd, stats: { colors: true },