From 701658a4f88ac03e71a9b5b0b5765ca06a8374a8 Mon Sep 17 00:00:00 2001 From: Evan You Date: Sat, 7 Apr 2018 03:43:57 -0400 Subject: [PATCH] fix: workaround for empty style chunk --- lib/build.js | 26 ++++++++++++++++++++++++-- lib/webpack/RemoveEmptyChunkPlugin.js | 12 ------------ lib/webpack/baseConfig.js | 9 --------- lib/webpack/clientConfig.js | 4 +--- lib/webpack/clientPlugin.js | 10 +++------- 5 files changed, 28 insertions(+), 33 deletions(-) delete mode 100644 lib/webpack/RemoveEmptyChunkPlugin.js diff --git a/lib/build.js b/lib/build.js index 6b91941e8e..02544882b7 100644 --- a/lib/build.js +++ b/lib/build.js @@ -8,6 +8,7 @@ module.exports = async function build (sourceDir, cliOptions = {}) { const { promisify } = require('util') const rimraf = promisify(require('rimraf')) const mkdirp = promisify(require('mkdirp')) + const readFile = promisify(fs.readFile) const writeFile = promisify(fs.writeFile) const prepare = require('./prepare') @@ -27,7 +28,7 @@ module.exports = async function build (sourceDir, cliOptions = {}) { const serverConfig = createServerConfig(options, cliOptions).toConfig() // compile! - await compile([clientConfig, serverConfig]) + const stats = await compile([clientConfig, serverConfig]) const serverBundle = require(path.resolve(outDir, 'manifest/server.json')) const clientManifest = require(path.resolve(outDir, 'manifest/client.json')) @@ -35,6 +36,10 @@ module.exports = async function build (sourceDir, cliOptions = {}) { // remove manifests after loading them. await rimraf(path.resolve(outDir, 'manifest')) + // fine and remove empty style chunk caused by + // https://github.com/webpack-contrib/mini-css-extract-plugin/issues/85 + await workaroundEmptyStyleChunk() + // create server renderer using built manifests const renderer = createBundleRenderer(serverBundle, { clientManifest, @@ -76,7 +81,7 @@ module.exports = async function build (sourceDir, cliOptions = {}) { reject(new Error(`Failed to compile with errors.`)) return } - resolve() + resolve(stats.toJson({ modules: false })) }) }) } @@ -121,4 +126,21 @@ module.exports = async function build (sourceDir, cliOptions = {}) { await mkdirp(path.dirname(filePath)) await writeFile(filePath, html) } + + async function workaroundEmptyStyleChunk () { + const styleChunk = stats.children[0].assets.find(a => { + return /styles\.\w{8}\.js$/.test(a.name) + }) + const styleChunkPath = path.resolve(outDir, styleChunk.name) + const styleChunkContent = await readFile(styleChunkPath, 'utf-8') + await rimraf(styleChunkPath) + // prepend it to app.js. + // this is necessary for the webpack runtime to work properly. + const appChunk = stats.children[0].assets.find(a => { + return /app\.\w{8}\.js$/.test(a.name) + }) + const appChunkPath = path.resolve(outDir, appChunk.name) + const appChunkContent = await readFile(appChunkPath, 'utf-8') + await writeFile(appChunkPath, styleChunkContent + appChunkContent) + } } diff --git a/lib/webpack/RemoveEmptyChunkPlugin.js b/lib/webpack/RemoveEmptyChunkPlugin.js deleted file mode 100644 index d2102c9022..0000000000 --- a/lib/webpack/RemoveEmptyChunkPlugin.js +++ /dev/null @@ -1,12 +0,0 @@ -// https://github.com/webpack-contrib/mini-css-extract-plugin/issues/85 -module.exports = class Plugin { - apply (compiler) { - compiler.hooks.emit.tap('vuepress-remove-empty-chunk', compilation => { - Object.keys(compilation.assets).forEach(name => { - if (/_assets\/js\/styles\.\w{8}\.js$/.test(name)) { - delete compilation.assets[name] - } - }) - }) - } -} diff --git a/lib/webpack/baseConfig.js b/lib/webpack/baseConfig.js index 8bb028adff..037888dad0 100644 --- a/lib/webpack/baseConfig.js +++ b/lib/webpack/baseConfig.js @@ -190,7 +190,6 @@ module.exports = function createBaseConfig ({ .set('optimization', { splitChunks: { cacheGroups: { - chunks: 'all', styles: { name: 'styles', // necessary for extraction to include md files as well @@ -201,14 +200,6 @@ module.exports = function createBaseConfig ({ } } }) - - // enforcing all styles extraction leaves an empty styles chunk. - // prevent it from being emitted. - // this is a bug in mini-css-extract-plugin - // https://github.com/webpack-contrib/mini-css-extract-plugin/issues/85 - config - .plugin('remove-empty-chunk') - .use(require('./RemoveEmptyChunkPlugin')) } return config diff --git a/lib/webpack/clientConfig.js b/lib/webpack/clientConfig.js index 57ec9d8945..143863ac46 100644 --- a/lib/webpack/clientConfig.js +++ b/lib/webpack/clientConfig.js @@ -15,9 +15,7 @@ module.exports = function createClientConfig (options, cliOptions) { // source contains it (although only uses it if it's native). setImmediate: false, global: false, - // process is injected via DefinePlugin, although some 3rd party - // libraries may require a mock to work properly (#934) - process: 'mock', + process: false, // prevent webpack from injecting mocks to Node native modules // that does not make sense for the client dgram: 'empty', diff --git a/lib/webpack/clientPlugin.js b/lib/webpack/clientPlugin.js index 33113786a5..240366e8b2 100644 --- a/lib/webpack/clientPlugin.js +++ b/lib/webpack/clientPlugin.js @@ -1,4 +1,4 @@ -// Temporarily copied from a dev build +// Temporarily hacked dev build var isJS = function (file) { return /\.js(\?[^.]+)?$/.test(file) } @@ -32,17 +32,13 @@ VueSSRClientPlugin.prototype.apply = function apply (compiler) { var allFiles = uniq(stats.assets .map(function (a) { return a.name })) - .filter(file => { - return !/styles\.\w{8}\.js$/.test(file) - }) var initialFiles = uniq(Object.keys(stats.entrypoints) .map(function (name) { return stats.entrypoints[name].assets }) .reduce(function (assets, all) { return all.concat(assets) }, []) .filter(function (file) { return isJS(file) || isCSS(file) })) - .filter(file => { - return !/styles\.\w{8}\.js$/.test(file) - }) + // Avoid preloading / injecting the style chunk + .filter(file => !/styles\.\w{8}\.js$/.test(file)) var asyncFiles = allFiles .filter(function (file) { return isJS(file) || isCSS(file) })