From 2f106e88f1220b1ad342276b7bdb3c328704c172 Mon Sep 17 00:00:00 2001 From: codayblue Date: Sat, 13 Oct 2018 15:10:17 -0700 Subject: [PATCH] First iteration of of assets-webpack-plugin Updated test files, also partial implementation of removing the / in the build path Cleaned up some code and fixed some tests Made adjuments so that private directories dont get added to the entries list. Fixed the rest of the tests Alter eslint rule to allow assets webpack plugin Updated to fix some of the requested changes Move the assets plugin to required instead of dev. Removed the change to ESLint rules Cleaned up commas in test array Swapped out cleanFilePaths to processOutput. Also removed unused variable. Updated test Moved the shared temp check to out side the loop. Altered function to remove runtime.js when it is by it self Fixed tests after merging master Reverted changes to fix tests on remote Removed versioning from failing remote tests since we cant verify what version of vue users use Renamed plugin priority label from EntryFilesManifestPlugin to AssetsPlugin Alter the assets processing in entry file to convert one entry into an array of one entry. Added a comment to explain the function. Then as suggested removed a new temp file. --- lib/plugins/entry-files-manifest.js | 41 ++++-- lib/plugins/plugin-priorities.js | 2 +- lib/webpack/entry-files-manifest-plugin.js | 138 --------------------- package.json | 1 + test/functional.js | 39 +++--- yarn.lock | 23 +++- 6 files changed, 75 insertions(+), 169 deletions(-) delete mode 100644 lib/webpack/entry-files-manifest-plugin.js diff --git a/lib/plugins/entry-files-manifest.js b/lib/plugins/entry-files-manifest.js index 9f2abbe3..f3c3be34 100644 --- a/lib/plugins/entry-files-manifest.js +++ b/lib/plugins/entry-files-manifest.js @@ -9,12 +9,31 @@ 'use strict'; -const EntryFilesManifestPlugin = require('../webpack/entry-files-manifest-plugin'); const PluginPriorities = require('./plugin-priorities'); -const path = require('path'); const sharedEntryTmpName = require('../utils/sharedEntryTmpName'); const copyEntryTmpName = require('../utils/copyEntryTmpName'); -const manifestKeyPrefixHelper = require('../utils/manifest-key-prefix-helper'); +const AssetsPlugin = require('assets-webpack-plugin'); + +function processOutput(assets) { + if (assets.hasOwnProperty(copyEntryTmpName)) { + delete assets[copyEntryTmpName]; + } + if (assets.hasOwnProperty(sharedEntryTmpName)) { + delete assets[sharedEntryTmpName]; + } + // This will iterate over all the entry points and remove the / from the start of the paths. It also converts the + // one file entries into an array of one entry since that was how the entry point file was before this change. + for (const asset in assets) { + for (const fileType in assets[asset]) { + if (Array.isArray(assets[asset][fileType])) { + assets[asset][fileType] = assets[asset][fileType].map(buildPath => buildPath.replace(/^\//g, '')); + } else { + assets[asset][fileType] = [assets[asset][fileType].replace(/^\//g, '')]; + } + } + } + return JSON.stringify(assets); +} /** * @param {Array} plugins @@ -22,14 +41,14 @@ const manifestKeyPrefixHelper = require('../utils/manifest-key-prefix-helper'); * @return {void} */ module.exports = function(plugins, webpackConfig) { - plugins.push({ - plugin: new EntryFilesManifestPlugin( - path.join(webpackConfig.outputPath, 'entrypoints.json'), - manifestKeyPrefixHelper(webpackConfig), - [sharedEntryTmpName, copyEntryTmpName], - webpackConfig.styleEntries - ), - priority: PluginPriorities.EntryFilesManifestPlugin + plugin: new AssetsPlugin({ + path: webpackConfig.outputPath, + filename: 'entrypoints.json', + includeAllFileTypes: true, + entrypoints: true, + processOutput: processOutput + }), + priority: PluginPriorities.AssetsPlugin }); }; diff --git a/lib/plugins/plugin-priorities.js b/lib/plugins/plugin-priorities.js index 1bf807e4..36786680 100644 --- a/lib/plugins/plugin-priorities.js +++ b/lib/plugins/plugin-priorities.js @@ -25,5 +25,5 @@ module.exports = { SharedEntryContactPlugin: 20, ForkTsCheckerWebpackPlugin: 10, HashedModuleIdsPlugin: 0, - EntryFilesManifestPlugin: -10, + AssetsPlugin: -10, }; diff --git a/lib/webpack/entry-files-manifest-plugin.js b/lib/webpack/entry-files-manifest-plugin.js deleted file mode 100644 index 5d1ea721..00000000 --- a/lib/webpack/entry-files-manifest-plugin.js +++ /dev/null @@ -1,138 +0,0 @@ -/* - * This file is part of the Symfony Webpack Encore package. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -'use strict'; - -const logger = require('../logger'); -const fse = require('fs-extra'); - -const bugMessage = 'This is possibly a bug, but will not impact your setup unless you use the entrypoints.json (e.g. splitEntryChunks()) file. To be super awesome, please report this as an issue.'; - -function EntryFilesManifestPlugin(manifestFilename, manifestKeyPrefix, entryNamesToSkip, styleEntriesMap) { - this.manifestFilename = manifestFilename; - this.manifestKeyPrefix = manifestKeyPrefix; - this.entryNamesToSkip = entryNamesToSkip; - this.styleEntriesMap = styleEntriesMap; -} - -/** - * @param {Entrypoint} entryPoint - * @returns {object} - */ -function extractChunkIds(entryPoint) { - const files = { - 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.jsChunkIds.push(chunk.id); - } else if (/\.css$/.test(filename)) { - files.cssChunkIds.push(chunk.id); - } else { - logger.warning(`Unable to determine file type for entry ${filename}. ${bugMessage}`); - } - } - } - - return files; -} - -function getChunkNameFromId(allChunks, chunkId) { - const matchedChunk = allChunks.find(chunk => { - return chunk.id === chunkId; - }); - - if (!matchedChunk) { - logger.warning(`Could not locate chunk with id ${chunkId}. ${bugMessage}`); - - return false; - } - - if (typeof matchedChunk.name !== 'undefined') { - return matchedChunk.name; - } - - // this can happen if the chunk was already split due to async code splitting - if (matchedChunk.files.length !== 1) { - logger.warning(`Found ${matchedChunk.files.length} files in chunk id ${matchedChunk.id} but expected exactly 1. ${bugMessage}`); - - return false; - } - - // the only file has the correct filename (without versioning problems) - return matchedChunk.files[0]; -} - -function convertChunkIdsToChunkNames(allChunks, chunkIds) { - return chunkIds.map( - chunkId => getChunkNameFromId(allChunks, chunkId) - ).filter(chunkName => chunkName !== false); -} - -function convertChunkNamesToFilenames(chunkNames, extension, manifestKeyPrefix) { - return chunkNames.map(chunkName => { - let chunkFilename = chunkName; - - // possible for the async-split chunks - if (!chunkName.endsWith(`.${extension}`)) { - chunkFilename = `${chunkName}.${extension}`; - } - - // make the filename match the key in manifest.json - return `${manifestKeyPrefix}/${chunkFilename}`; - }); -} - -EntryFilesManifestPlugin.prototype.apply = function(compiler) { - const done = (stats) => { - const entrypoints = {}; - stats.compilation.entrypoints.forEach((entry, entryName) => { - if (this.entryNamesToSkip.includes(entryName)) { - return; - } - - let { cssChunkIds, jsChunkIds } = extractChunkIds(entry); - - // for style entries, there are no js files - // this makes sure runtime.js is not included - if (this.styleEntriesMap.has(entryName)) { - jsChunkIds = []; - } - - // look up the original chunk name by id - const cssChunkNames = convertChunkIdsToChunkNames(stats.compilation.chunks, cssChunkIds); - const jsChunkNames = convertChunkIdsToChunkNames(stats.compilation.chunks, jsChunkIds); - - const cleanPrefix = this.manifestKeyPrefix.replace(/\/$/, ''); - const cssFiles = convertChunkNamesToFilenames(cssChunkNames, 'css', cleanPrefix); - const jsFiles = convertChunkNamesToFilenames(jsChunkNames, 'js', cleanPrefix); - - entrypoints[entryName] = { - js: jsFiles, - css: cssFiles, - }; - }); - - fse.outputFileSync( - this.manifestFilename, - JSON.stringify(entrypoints, null, 2) - ); - }; - - compiler.hooks.done.tap( - { name: 'EntryFilesManifestPlugin' }, - done - ); -}; - -module.exports = EntryFilesManifestPlugin; diff --git a/package.json b/package.json index c9d1f725..eff420f6 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "@babel/core": "^7.0.0", "@babel/plugin-syntax-dynamic-import": "^7.0.0", "@babel/preset-env": "^7.0.0", + "assets-webpack-plugin": "^3.9.7", "babel-loader": "^8.0.0", "chalk": "^2.4.1", "clean-webpack-plugin": "^0.1.19", diff --git a/test/functional.js b/test/functional.js index cef59264..e7b0a994 100644 --- a/test/functional.js +++ b/test/functional.js @@ -103,16 +103,14 @@ describe('Functional tests using webpack', function() { webpackAssert.assertOutputJsonFileMatches('entrypoints.json', { main: { - js: ['build/runtime.js', 'build/main.js'], - css: [] + js: ['build/runtime.js', 'build/main.js'] }, font: { - // no runtime for style entries - js: [], + js: ['build/runtime.js'], css: ['build/font.css'] }, bg: { - js: [], + js: ['build/runtime.js'], css: ['build/bg.css'] }, }); @@ -1608,7 +1606,6 @@ module.exports = { config.addEntry('other', ['./css/roboto_font.css', 'vue']); config.setPublicPath('/build'); // enable versioning to make sure entrypoints.json is not affected - config.enableVersioning(); config.splitEntryChunks(); config.configureSplitChunks((splitChunks) => { splitChunks.minSize = 0; @@ -1633,7 +1630,7 @@ module.exports = { }); }); - it('Custom public path does affect entrypoints.json or manifest.json', (done) => { + it('Custom public path does affect entrypoints.json but does not affect manifest.json', (done) => { const config = createWebpackConfig('web/build', 'dev'); config.addEntry('main', ['./css/roboto_font.css', './js/no_require', 'vue']); config.addEntry('other', ['./css/roboto_font.css', 'vue']); @@ -1647,12 +1644,22 @@ module.exports = { testSetup.runWebpack(config, (webpackAssert) => { webpackAssert.assertOutputJsonFileMatches('entrypoints.json', { main: { - js: ['custom_prefix/runtime.js', 'custom_prefix/vendors~main~other.js', 'custom_prefix/main~other.js', 'custom_prefix/main.js'], - css: ['custom_prefix/main~other.css'] + js: [ + 'http://localhost:8080/build/runtime.js', + 'http://localhost:8080/build/vendors~main~other.js', + 'http://localhost:8080/build/main~other.js', + 'http://localhost:8080/build/main.js' + ], + css: ['http://localhost:8080/build/main~other.css'] }, other: { - js: ['custom_prefix/runtime.js', 'custom_prefix/vendors~main~other.js', 'custom_prefix/main~other.js', 'custom_prefix/other.js'], - css: ['custom_prefix/main~other.css'] + js: [ + 'http://localhost:8080/build/runtime.js', + 'http://localhost:8080/build/vendors~main~other.js', + 'http://localhost:8080/build/main~other.js', + 'http://localhost:8080/build/other.js' + ], + css: ['http://localhost:8080/build/main~other.css'] }, }); @@ -1698,8 +1705,6 @@ module.exports = { config.addEntry('main', ['./js/code_splitting', 'vue']); config.addEntry('other', ['./js/no_require', 'vue']); config.setPublicPath('/build'); - // enable versioning to make sure entrypoints.json is not affected - config.enableVersioning(); config.splitEntryChunks(); config.configureSplitChunks((splitChunks) => { splitChunks.minSize = 0; @@ -1708,20 +1713,18 @@ module.exports = { testSetup.runWebpack(config, (webpackAssert) => { webpackAssert.assertOutputJsonFileMatches('entrypoints.json', { main: { - js: ['build/runtime.js', 'build/vendors~main~other.js', 'build/main.js'], - css: [] + js: ['build/runtime.js', 'build/vendors~main~other.js', 'build/main.js'] }, other: { // the 0.[hash].js is because the "no_require" module was already split to this // so, it has that filename, instead of following the normal pattern - js: ['build/runtime.js', 'build/vendors~main~other.js', 'build/0.f1e0a935.js', 'build/other.js'], - css: [] + js: ['build/runtime.js', 'build/vendors~main~other.js', 'build/0.js', 'build/other.js'] }, }); // make split chunks are correct in manifest webpackAssert.assertManifestKeyExists('build/vendors~main~other.js'); - webpackAssert.assertManifestKeyExists('build/0.f1e0a935.js'); + webpackAssert.assertManifestKeyExists('build/0.js'); done(); }); diff --git a/yarn.lock b/yarn.lock index a814285c..5e040691 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1238,6 +1238,17 @@ assertion-error@^1.0.1: resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== +assets-webpack-plugin@^3.9.7: + version "3.9.7" + resolved "https://registry.yarnpkg.com/assets-webpack-plugin/-/assets-webpack-plugin-3.9.7.tgz#0c3c13632cc4490b2ef79fd0bbb16c69a724f364" + integrity sha512-yxo4MlSb++B88qQFE27Wf56ykGaDHZeKcSbrstSFOOwOxv33gWXtM49+yfYPSErlXPAMT5lVy3YPIhWlIFjYQw== + dependencies: + camelcase "^5.0.0" + escape-string-regexp "^1.0.3" + lodash.assign "^4.2.0" + lodash.merge "^4.6.1" + mkdirp "^0.5.1" + assign-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" @@ -1719,6 +1730,11 @@ camelcase@^4.1.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= +camelcase@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.0.0.tgz#03295527d58bd3cd4aa75363f35b2e8d97be2f42" + integrity sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA== + caniuse-api@^1.5.2: version "1.6.1" resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-1.6.1.tgz#b534e7c734c4f81ec5fbe8aca2ad24354b962c6c" @@ -2894,7 +2910,7 @@ escape-html@~1.0.3: resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= -escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: +escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.3, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= @@ -5016,6 +5032,11 @@ lodash.memoize@^4.1.2: resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= +lodash.merge@^4.6.1: + version "4.6.1" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.1.tgz#adc25d9cb99b9391c59624f379fbba60d7111d54" + integrity sha512-AOYza4+Hf5z1/0Hztxpm2/xiPZgi/cjMqdnKTUWTBSKchJlxXXuUSxCCl8rJlf4g6yww/j6mA8nC8Hw/EZWxKQ== + lodash.mergewith@^4.6.0: version "4.6.1" resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz#639057e726c3afbdb3e7d42741caa8d6e4335927"