From d1454febd13c8e008e5dec4f13e7d55bf4eb4d18 Mon Sep 17 00:00:00 2001 From: Jack Zhao Date: Sun, 20 May 2018 10:25:57 -0700 Subject: [PATCH] Webpack4 (#4490) * - [x] Upgrade to webpack 4.8.X - [x] Utilize webpack 4 development and production modes - [x] Upgrade webpack dev server - [x] Webpack 4 compatible release of thread-loader - [x] Webpack 4 compatible release of HtmlWebpackPlugin - [x] Webpack 4 compatible release of SwPrecacheWebpackPlugin - [x] Webpack 4 compatible release of WebpackManifestPlugin - [x] Update README - [x] Update WebpackDevServerUtils - [x] Update InterpolateHtmlPlugin - [x] Update ModuleScopePlugin - [x] Update WatchMissingNodeModulesPlugin - [x] Move UglifyJS options to webpack 4 optimize - [x] Move InterpolateHtmlPlugin to make it tapable on HtmlWebpackPlugin - [x] vendor splitting via splitChunks.splitChunks (https://twitter.com/wSokra/status/969633336732905474) - [x] long term caching via splitChunks.runtimeChunk (https://twitter.com/wSokra/status/969679223278505985) - [x] Make sure process.env.NODE_ENV is proxied correctly to `react-error-overlay` - [x] Implicit webpack.NamedModulesPlugin in dev config as its default in webpack 4 - [x] Disable webpack performance hints as we have our own filesize reporter - [x] Replace ExtractTextPlugin with MiniCssExtractPlugin - [x] Switch to css whole file minification via OptimizeCSSAssetsPlugin rather than per module css minification to gain performance * disable module concatenation * fix cleanup * fix optimization * restore tmp removal * preserve * fix css tests * fix test run * fix svg test * revert tmp dir * fix import * fix import * help debugging * fix tests * fix sass test * restore cleanup --- .../config/webpack.config.prod.js | 2 + .../kitchensink/integration/initDOM.js | 19 ++-- .../kitchensink/integration/webpack.test.js | 90 ++++++++----------- tasks/e2e-installs.sh | 2 +- 4 files changed, 47 insertions(+), 66 deletions(-) diff --git a/packages/react-scripts/config/webpack.config.prod.js b/packages/react-scripts/config/webpack.config.prod.js index 4d04909a8b4..77d30c067ed 100644 --- a/packages/react-scripts/config/webpack.config.prod.js +++ b/packages/react-scripts/config/webpack.config.prod.js @@ -115,6 +115,8 @@ module.exports = { .replace(/\\/g, '/'), }, optimization: { + // webpack-manifest-plugin currently does not play well with ConcatenatedModule + concatenateModules: false, minimizer: [ new UglifyJsPlugin({ uglifyOptions: { diff --git a/packages/react-scripts/fixtures/kitchensink/integration/initDOM.js b/packages/react-scripts/fixtures/kitchensink/integration/initDOM.js index 3d0eb7a1c9c..36e8de9999f 100644 --- a/packages/react-scripts/fixtures/kitchensink/integration/initDOM.js +++ b/packages/react-scripts/fixtures/kitchensink/integration/initDOM.js @@ -12,7 +12,7 @@ const path = require('path'); const { expect } = require('chai'); let getMarkup; -let resourceLoader; +export let resourceLoader; if (process.env.E2E_FILE) { const file = path.isAbsolute(process.env.E2E_FILE) @@ -47,14 +47,11 @@ if (process.env.E2E_FILE) { resourceLoader = (resource, callback) => resource.defaultFetch(callback); } else { - it.only( - 'can run jsdom (at least one of "E2E_FILE" or "E2E_URL" environment variables must be provided)', - () => { - expect( - new Error("This isn't the error you are looking for.") - ).to.be.undefined(); - } - ); + it.only('can run jsdom (at least one of "E2E_FILE" or "E2E_URL" environment variables must be provided)', () => { + expect( + new Error("This isn't the error you are looking for.") + ).to.be.undefined(); + }); } export default feature => @@ -62,10 +59,6 @@ export default feature => const markup = await getMarkup(); const host = process.env.E2E_URL || 'http://www.example.org/spa:3000'; const doc = jsdom.jsdom(markup, { - features: { - FetchExternalResources: ['script', 'css'], - ProcessExternalResources: ['script'], - }, created: (_, win) => win.addEventListener('ReactFeatureDidMount', () => resolve(doc), true), deferClose: true, diff --git a/packages/react-scripts/fixtures/kitchensink/integration/webpack.test.js b/packages/react-scripts/fixtures/kitchensink/integration/webpack.test.js index c8dd07f0922..ff3d383219d 100644 --- a/packages/react-scripts/fixtures/kitchensink/integration/webpack.test.js +++ b/packages/react-scripts/fixtures/kitchensink/integration/webpack.test.js @@ -6,78 +6,68 @@ */ import { expect } from 'chai'; -import initDOM from './initDOM'; +import initDOM, { resourceLoader } from './initDOM'; +import url from 'url'; + +const matchCSS = (doc, regexes) => { + if (process.env.E2E_FILE) { + const elements = doc.getElementsByTagName('link'); + let href = ""; + for (const elem of elements) { + if (elem.rel === 'stylesheet') { + href = elem.href; + } + } + resourceLoader( + { url: url.parse(href) }, + (_, textContent) => { + for (const regex of regexes) { + expect(textContent).to.match(regex); + } + } + ); + + } else { + for (let i = 0; i < regexes.length; ++i) { + expect(doc.getElementsByTagName('style')[i].textContent.replace(/\s/g, '')).to.match(regexes[i]); + } + } +} describe('Integration', () => { describe('Webpack plugins', () => { it('css inclusion', async () => { const doc = await initDOM('css-inclusion'); - - expect( - doc.getElementsByTagName('style')[0].textContent.replace(/\s/g, '') - ).to.match(/html\{/); - expect( - doc.getElementsByTagName('style')[1].textContent.replace(/\s/g, '') - ).to.match(/#feature-css-inclusion\{background:.+;color:.+}/); + matchCSS(doc, [/html\{/, /#feature-css-inclusion\{background:.+;color:.+}/]); }); it('css modules inclusion', async () => { const doc = await initDOM('css-modules-inclusion'); - - expect( - doc.getElementsByTagName('style')[0].textContent.replace(/\s/g, '') - ).to.match(/.+style_cssModulesInclusion__.+\{background:.+;color:.+}/); - expect( - doc.getElementsByTagName('style')[1].textContent.replace(/\s/g, '') - ).to.match( - /.+assets_cssModulesIndexInclusion__.+\{background:.+;color:.+}/ - ); + matchCSS(doc, [/.+style_cssModulesInclusion__.+\{background:.+;color:.+}/, + /.+assets_cssModulesIndexInclusion__.+\{background:.+;color:.+}/]); }); it('scss inclusion', async () => { const doc = await initDOM('scss-inclusion'); - - expect( - doc.getElementsByTagName('style')[0].textContent.replace(/\s/g, '') - ).to.match(/#feature-scss-inclusion\{background:.+;color:.+}/); + matchCSS(doc, [/#feature-scss-inclusion\{background:.+;color:.+}/]); }); it('scss modules inclusion', async () => { const doc = await initDOM('scss-modules-inclusion'); - - expect( - doc.getElementsByTagName('style')[0].textContent.replace(/\s/g, '') - ).to.match( - /.+scss-styles_scssModulesInclusion.+\{background:.+;color:.+}/ - ); - expect( - doc.getElementsByTagName('style')[1].textContent.replace(/\s/g, '') - ).to.match( - /.+assets_scssModulesIndexInclusion.+\{background:.+;color:.+}/ - ); + matchCSS(doc, [/.+scss-styles_scssModulesInclusion.+\{background:.+;color:.+}/, + /.+assets_scssModulesIndexInclusion.+\{background:.+;color:.+}/]); + }); it('sass inclusion', async () => { const doc = await initDOM('sass-inclusion'); - - expect( - doc.getElementsByTagName('style')[0].textContent.replace(/\s/g, '') - ).to.match(/#feature-sass-inclusion\{background:.+;color:.+}/); + matchCSS(doc, [/#feature-sass-inclusion\{background:.+;color:.+}/]); }); it('sass modules inclusion', async () => { const doc = await initDOM('sass-modules-inclusion'); - - expect( - doc.getElementsByTagName('style')[0].textContent.replace(/\s/g, '') - ).to.match( - /.+sass-styles_sassModulesInclusion.+\{background:.+;color:.+}/ - ); - expect( - doc.getElementsByTagName('style')[1].textContent.replace(/\s/g, '') - ).to.match( - /.+assets_sassModulesIndexInclusion.+\{background:.+;color:.+}/ - ); + matchCSS(doc, [/.+sass-styles_sassModulesInclusion.+\{background:.+;color:.+}/, + /.+assets_sassModulesIndexInclusion.+\{background:.+;color:.+}/]); }); it('graphql files inclusion', async () => { @@ -124,7 +114,6 @@ describe('Integration', () => { it('svg inclusion', async () => { const doc = await initDOM('svg-inclusion'); - expect(doc.getElementById('feature-svg-inclusion').src).to.match( /\/static\/media\/logo\..+\.svg$/ ); @@ -140,10 +129,7 @@ describe('Integration', () => { it('svg in css', async () => { const doc = await initDOM('svg-in-css'); - - expect( - doc.getElementsByTagName('style')[0].textContent.replace(/\s/g, '') - ).to.match(/\/static\/media\/logo\..+\.svg/); + matchCSS(doc, [/\/static\/media\/logo\..+\.svg/]); }); it('unknown ext inclusion', async () => { diff --git a/tasks/e2e-installs.sh b/tasks/e2e-installs.sh index 6caf114c572..b58cd5eafca 100755 --- a/tasks/e2e-installs.sh +++ b/tasks/e2e-installs.sh @@ -86,7 +86,7 @@ yarn # Start local registry tmp_registry_log=`mktemp` -nohup npx verdaccio@2.7.2 &>$tmp_registry_log & +nohup npx verdaccio@2.7.2 -c tasks/verdaccio.yaml &>$tmp_registry_log & # Wait for `verdaccio` to boot grep -q 'http address' <(tail -f $tmp_registry_log)