Skip to content

Hello Webpack4 ⭐️ #324

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 79 commits into from
Jul 18, 2018
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
022362f
Upgrading packages to Webpack 4 and replacing extract text by
weaverryan May 16, 2018
89499fd
Adding mode option
weaverryan May 16, 2018
43b6e30
Removing CommonsChunkPlugin & moving named modules logic
weaverryan May 16, 2018
9601780
upgrading all other dependencies & handling babel env changes
weaverryan May 16, 2018
a1873fc
Fixing deprecated hooks
weaverryan May 16, 2018
02dce21
Updating test: mini-css-extract extracts async chunks for css
weaverryan May 16, 2018
07add8f
[Minor] Hashes changed in the test
weaverryan May 16, 2018
f9134b2
[Minor] More test updates for now CSS async are now extracted
weaverryan May 16, 2018
dfb3611
Moving Uglify configuration
weaverryan May 16, 2018
0eac2f0
Removing old test
weaverryan May 16, 2018
c4c7aec
Updating to new babel react package
weaverryan May 16, 2018
172fb62
Completely removing CoffeeScript
weaverryan May 16, 2018
8879114
Fixing more @babel/preset-env spots
weaverryan May 16, 2018
4ec4fcb
Upgrading to latest vue-loader
weaverryan May 16, 2018
eb8005f
fixing some version strings in tests
weaverryan May 16, 2018
228d3ff
Fixing test - it was a false failure
weaverryan May 16, 2018
735bec0
Fixing test related to uglify
weaverryan May 16, 2018
7f244c4
Fixing test - internal option location changed
weaverryan May 16, 2018
5d940f0
Installing the now-required webpack-cli
weaverryan May 16, 2018
3ae0fe0
Updating our custom formatting of vue loader problems
weaverryan May 17, 2018
d91371a
enhancing createSharedEntry test
weaverryan May 17, 2018
9c9becb
Re-adding the traditional createSharedEntry functionality
weaverryan May 17, 2018
8c9405c
improving createSharedEntry test
weaverryan May 19, 2018
262c206
not using vendor, as it could conflict with built-in cache group
weaverryan May 19, 2018
3320418
Adding a warning of you accidentally override a core cache group
weaverryan May 24, 2018
51e6088
Hiding the "built at" output
weaverryan May 24, 2018
d1e9731
Fixing a babelrc change
weaverryan May 24, 2018
d31eb5d
Adding support for browserslist in package.json!
weaverryan May 28, 2018
18fd553
Adding support for configuring splitChunks.chunks to "all"
weaverryan May 29, 2018
6cc4624
fixing copy paste
weaverryan Jun 9, 2018
a2995b6
enhancing test to also test css splitting
weaverryan Jun 9, 2018
7fda6fd
Adding support for dynamic imports out-of-the-box
weaverryan Jun 9, 2018
51aade6
WIP - changing format of "features" to make room for version
weaverryan Jun 9, 2018
9a9f2b0
Renaming method for future clarity
weaverryan Jun 10, 2018
f733bb2
Adding new version-handling logic for optional dependencies
weaverryan Jun 10, 2018
81a079a
upgrading to @babel/plugin-transform-react-jsx
weaverryan Jun 10, 2018
6b17c6f
fixing reversed logic
weaverryan Jun 10, 2018
724a67d
finishing preact babel changes after upgrade
weaverryan Jun 10, 2018
05c5a24
upgrading to @babel/plugin-syntax-dynamic-import
weaverryan Jun 10, 2018
1c41070
Outputting the required version with the "yarn add" recommendations
weaverryan Jun 10, 2018
46a00df
removing failing test
weaverryan Jun 10, 2018
301bd21
Fixing new loading for the .babelrc file
weaverryan Jun 11, 2018
014c304
Fixing very old bug in tests, where the "cwd" passed to parseRuntime()
weaverryan Jun 11, 2018
097592f
updating broken test
weaverryan Jun 11, 2018
cbf478f
fixing lint
weaverryan Jun 11, 2018
bdf201a
A hacky attempt at supporting createSharedEntry()
weaverryan Jun 22, 2018
049343f
adding a test to prove shared entry code is not double-included
weaverryan Jun 23, 2018
de9568d
Omitting the _tmp_shared from the manifest & entrypoints files
weaverryan Jun 23, 2018
2cf72e0
Making shared entry working with versioning
weaverryan Jun 23, 2018
ce51d27
fixing typos
weaverryan Jun 23, 2018
2e53737
Clear errors for removed methods
weaverryan Jun 23, 2018
f3f8d09
Using semver to enforce our plugin versions a bit better
weaverryan Jun 26, 2018
9558c89
making our entry files plugin last, to catch any entry points that may
weaverryan Jun 26, 2018
ce8c0df
Verify that the runtime files are included in entrypoints.json
weaverryan Jun 26, 2018
eaebb31
moving test
weaverryan Jul 1, 2018
3b65403
Fixing entrypoints.json so that it points to the unversioned filename
weaverryan Jul 12, 2018
5ba3c11
Adding Encore.splitEntryChunks() to enable that new feature easier
weaverryan Jul 12, 2018
13d7c5b
Fixing bad function name
weaverryan Jul 13, 2018
27f3534
Fixing lint issues
weaverryan Jul 13, 2018
2573899
Fixing windows problems with \ in paths
weaverryan Jul 13, 2018
734c59a
removing support for node 7
weaverryan Jul 13, 2018
1d5786f
Fixing problems with windows slashes in our hacky "require" dumped code
weaverryan Jul 13, 2018
5b19827
*actually* removing Node 7 support
weaverryan Jul 13, 2018
fe31d7d
re-adding webpack-dev-server
weaverryan Jul 14, 2018
d7cf989
Fixing bad filename in changelog
weaverryan Jul 15, 2018
1acc67a
Changing | to ||, which is the correct format
weaverryan Jul 16, 2018
cf0192f
Automatically hashing split filenames on production
weaverryan Jul 16, 2018
55631cc
Fixing a bug where entrypoints.json contained bad names in production
weaverryan Jul 17, 2018
9d2043c
Marking methods as deprecated to help auto-completion
weaverryan Jul 17, 2018
f9a0799
Fixing a bug where runtime.js would appear for "style" entries in
weaverryan Jul 17, 2018
75ec093
Always outputting runtime.js
weaverryan Jul 17, 2018
6de05cf
preventing shared entry & split chunks from being used together
weaverryan Jul 17, 2018
20ad1bd
fixing comment
weaverryan Jul 17, 2018
7db0fcb
Adding new Encore.enableSingleRuntimeChunk() + BC layer
weaverryan Jul 17, 2018
75ea6ea
Fixing a bug where logs could break JSON output
weaverryan Jul 17, 2018
4b43766
Adding missing config in test
weaverryan Jul 17, 2018
df2a58f
Fixing a bug where async-split chunks caused undefined in
weaverryan Jul 17, 2018
3c1b790
using latest webpack-cli + updating deps
weaverryan Jul 17, 2018
ab109cd
Changing entrypoints.json values to include the manifest key prefix
weaverryan Jul 18, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions lib/config-generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ const tmp = require('tmp');
const fs = require('fs');
const path = require('path');
const stringEscaper = require('./utils/string-escaper');
const crypto = require('crypto');

class ConfigGenerator {
/**
Expand Down Expand Up @@ -365,6 +366,25 @@ class ConfigGenerator {
let splitChunks = {
chunks: this.webpackConfig.shouldSplitEntryChunks ? 'all' : 'async'
};

// hash the split filenames in production to protect exposing entry names
if (this.webpackConfig.shouldSplitEntryChunks && this.webpackConfig.isProduction()) {
// taken from SplitChunksPlugin
const hashFilename = name => {
return crypto
.createHash('md4')
.update(name)
.digest('hex')
.slice(0, 8);
};

splitChunks.name = function(module, chunks, cacheGroup) {
const names = chunks.map(c => c.name);

return cacheGroup + '~' + hashFilename(names.join('~'));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure ~ is a good separator choice, it's part of the "unsafe characters" listed in this RFC: http://www.ietf.org/rfc/rfc1738.txt

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's the separator used by default in Webpack 4

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kinda weird they went with that one, but let's keep it that way then

};
}

if (this.webpackConfig.sharedCommonsEntryName) {
const cacheGroups = {};
cacheGroups[this.webpackConfig.sharedCommonsEntryName] = {
Expand Down
29 changes: 23 additions & 6 deletions lib/webpack/entry-files-manifest-plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,19 @@ function EntryFilesManifestPlugin(manifestFilename, entryNamesToSkip) {
* @param {Entrypoint} entryPoint
* @returns {object}
*/
function extractFiles(entryPoint) {
function extractChunkIds(entryPoint) {
const files = {
jsFiles: [],
cssFiles: [],
jsChunkIds: [],
cssChunkIds: [],
};

for (let chunk of entryPoint.chunks) {
for (let filename of chunk.files) {
if (/\.js$/.test(filename)) {
// use the chunk id because we do not want the versioned filename
files.jsFiles.push(`${chunk.id}.js`);
files.jsChunkIds.push(chunk.id);
} else if (/\.css$/.test(filename)) {
files.cssFiles.push(`${chunk.id}.css`);
files.cssChunkIds.push(chunk.id);
} else {
logger.debug(`Unable to determine file type for entry ${filename}. This is possibly a bug, but will not impact your setup unless you use the entrypoints.json file. To be super awesome, please report this as an issue.`);
}
Expand All @@ -43,6 +43,16 @@ function extractFiles(entryPoint) {
return files;
}

function getChunkNameFromId(allChunks, chunkId) {
return allChunks.find(chunk => {
return chunk.id === chunkId;
}).name;
}

function convertChunkNamesToFilenames(chunkNames, extension) {
return chunkNames.map(chunkName => `${chunkName}.${extension}`);
}

EntryFilesManifestPlugin.prototype.apply = function(compiler) {
const done = (stats) => {
const entrypoints = {};
Expand All @@ -51,7 +61,14 @@ EntryFilesManifestPlugin.prototype.apply = function(compiler) {
return;
}

const { cssFiles, jsFiles } = extractFiles(entry);
const { cssChunkIds, jsChunkIds } = extractChunkIds(entry);

// look up the original chunk name by id
const cssChunkNames = cssChunkIds.map(chunkId => getChunkNameFromId(stats.compilation.chunks, chunkId));
const jsChunkNames = jsChunkIds.map(chunkId => getChunkNameFromId(stats.compilation.chunks, chunkId));
const cssFiles = convertChunkNamesToFilenames(cssChunkNames, 'css');
const jsFiles = convertChunkNamesToFilenames(jsChunkNames, 'js');

entrypoints[entryName] = {
js: jsFiles,
css: cssFiles,
Expand Down
26 changes: 26 additions & 0 deletions test/config-generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -824,4 +824,30 @@ describe('The config-generator function', () => {
});
});
});

describe('Test shouldSplitEntryChunks', () => {
it('Not production', () => {
const config = createConfig();
config.outputPath = '/tmp/public/build';
config.setPublicPath('/build/');
config.splitEntryChunks();

const actualConfig = configGenerator(config);
expect(actualConfig.optimization.splitChunks.chunks).to.equal('all');
expect(actualConfig.optimization.splitChunks.name).to.be.undefined;
});

it('Yes production', () => {
const runtimeConfig = new RuntimeConfig();
runtimeConfig.environment = 'production';
const config = createConfig(runtimeConfig);
config.outputPath = '/tmp/public/build';
config.setPublicPath('/build/');
config.splitEntryChunks();

const actualConfig = configGenerator(config);
expect(actualConfig.optimization.splitChunks.chunks).to.equal('all');
expect(actualConfig.optimization.splitChunks.name).to.be.a('function');
});
});
});
30 changes: 30 additions & 0 deletions test/functional.js
Original file line number Diff line number Diff line change
Expand Up @@ -1302,6 +1302,36 @@ module.exports = {
done();
});
});

it('Use splitChunks in production mode', (done) => {
const config = createWebpackConfig('web/build', 'production');
config.addEntry('main', ['./css/roboto_font.css', './js/no_require', 'vue']);
config.addEntry('other', ['./css/roboto_font.css', 'vue']);
config.setPublicPath('/build');
config.splitEntryChunks();
config.configureSplitChunks((splitChunks) => {
splitChunks.minSize = 0;
});

testSetup.runWebpack(config, (webpackAssert) => {
// in production, we hash the chunk names to avoid exposing any extra details
webpackAssert.assertOutputJsonFileMatches('entrypoints.json', {
main: {
js: ['vendors~cc515e6e.js', 'default~cc515e6e.js', 'main.js'],
css: ['default~cc515e6e.css']
},
other: {
js: ['vendors~cc515e6e.js', 'default~cc515e6e.js', 'other.js'],
css: ['default~cc515e6e.css']
},
});

// make split chunks are correct in manifest
webpackAssert.assertManifestKeyExists('build/vendors~cc515e6e.js');

done();
});
});
});
});
});