Skip to content

Commit f4411a8

Browse files
committed
feat: (wip) upgrade to webpack 4
1 parent f744040 commit f4411a8

File tree

13 files changed

+309
-138
lines changed

13 files changed

+309
-138
lines changed

packages/@vue/cli-plugin-typescript/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
"@types/node": "^9.3.0",
2626
"fork-ts-checker-webpack-plugin": "^0.4.0",
2727
"globby": "^8.0.1",
28-
"ts-loader": "^3.4.0",
28+
"ts-loader": "^4.0.1",
2929
"tslint": "^5.9.1",
3030
"typescript": "^2.7.2"
3131
},

packages/@vue/cli-service/lib/Service.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ const Config = require('webpack-chain')
88
const PluginAPI = require('./PluginAPI')
99
const loadEnv = require('./util/loadEnv')
1010
const defaultsDeep = require('lodash.defaultsdeep')
11+
const ChainedMap = require('webpack-chain/src/ChainedMap')
1112
const { warn, error, isPlugin } = require('@vue/cli-shared-utils')
1213

1314
const { defaults, validate } = require('./options')
@@ -131,6 +132,16 @@ module.exports = class Service {
131132

132133
resolveChainableWebpackConfig () {
133134
const chainableConfig = new Config()
135+
136+
// temporary patch for new option "optimization" for wepback 4
137+
chainableConfig.optimization = new ChainedMap(chainableConfig)
138+
const toConfig = chainableConfig.toConfig
139+
chainableConfig.toConfig = function () {
140+
const res = toConfig.call(this)
141+
res.optimization = this.optimization.entries()
142+
return res
143+
}
144+
134145
// apply chains
135146
this.webpackChainFns.forEach(fn => fn(chainableConfig))
136147
return chainableConfig

packages/@vue/cli-service/lib/config/app.js

Lines changed: 36 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,6 @@ module.exports = (api, options) => {
77
return
88
}
99

10-
// inject preload/prefetch to HTML
11-
const PreloadPlugin = require('../webpack/PreloadPlugin')
12-
webpackConfig
13-
.plugin('preload')
14-
.use(PreloadPlugin, [{
15-
rel: 'preload',
16-
include: 'initial',
17-
fileBlacklist: [/\.map$/, /hot-update\.js$/]
18-
}])
19-
20-
webpackConfig
21-
.plugin('prefetch')
22-
.use(PreloadPlugin, [{
23-
rel: 'prefetch',
24-
include: 'asyncChunks'
25-
}])
26-
2710
// HTML plugin
2811
const fs = require('fs')
2912
const htmlPath = api.resolve('public/index.html')
@@ -38,7 +21,33 @@ module.exports = (api, options) => {
3821
)
3922
])
4023

24+
// copy static assets in public/
25+
webpackConfig
26+
.plugin('copy')
27+
.use(require('copy-webpack-plugin'), [[{
28+
from: api.resolve('public'),
29+
to: api.resolve(options.outputDir),
30+
ignore: ['index.html', '.DS_Store']
31+
}]])
32+
4133
if (process.env.NODE_ENV === 'production') {
34+
// inject preload/prefetch to HTML
35+
const PreloadPlugin = require('../webpack/PreloadPlugin')
36+
webpackConfig
37+
.plugin('preload')
38+
.use(PreloadPlugin, [{
39+
rel: 'preload',
40+
include: 'initial',
41+
fileBlacklist: [/\.map$/, /hot-update\.js$/]
42+
}])
43+
44+
webpackConfig
45+
.plugin('prefetch')
46+
.use(PreloadPlugin, [{
47+
rel: 'prefetch',
48+
include: 'asyncChunks'
49+
}])
50+
4251
// minify HTML
4352
webpackConfig
4453
.plugin('html')
@@ -54,64 +63,33 @@ module.exports = (api, options) => {
5463
chunksSortMode: 'dependency'
5564
})])
5665

57-
// Code splitting configs for better long-term caching
58-
// This needs to be updated when upgrading to webpack 4
59-
const CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin')
66+
// // Code splitting configs for better long-term caching
67+
// // This needs to be updated when upgrading to webpack 4
68+
// const CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin')
6069

6170
if (!options.dll) {
62-
// extract vendor libs into its own chunk for better caching, since they
63-
// are more likely to stay the same.
64-
webpackConfig
65-
.plugin('split-vendor')
66-
.use(CommonsChunkPlugin, [{
67-
name: 'vendor',
68-
minChunks (module) {
69-
// any required modules inside node_modules are extracted to vendor
70-
return (
71-
module.resource &&
72-
/\.js$/.test(module.resource) &&
73-
module.resource.indexOf(`node_modules`) > -1
74-
)
75-
}
76-
}])
77-
78-
// extract webpack runtime and module manifest to its own file in order to
79-
// prevent vendor hash from being updated whenever app bundle is updated
80-
webpackConfig
81-
.plugin('split-manifest')
82-
.use(CommonsChunkPlugin, [{
83-
name: 'manifest',
84-
minChunks: Infinity
85-
}])
71+
webpackConfig.optimization
72+
.set('runtimeChunk', true)
73+
.set('splitChunks', {
74+
chunks: 'all'
75+
})
8676

8777
// inline the manifest chunk into HTML
8878
webpackConfig
8979
.plugin('inline-manifest')
9080
.use(require('../webpack/InlineSourcePlugin'), [{
91-
include: /manifest\..*\.js$/
81+
include: /runtime~.*\.js$/
9282
}])
9383

9484
// since manifest is inlined, don't preload it anymore
9585
webpackConfig
9686
.plugin('preload')
9787
.tap(([options]) => {
98-
options.fileBlacklist.push(/manifest\..*\.js$/)
88+
options.fileBlacklist.push(/runtime~.*\.js$/)
9989
return [options]
10090
})
10191
}
10292

103-
// This CommonsChunkPlugin instance extracts shared chunks from async
104-
// chunks and bundles them in a separate chunk, similar to the vendor chunk
105-
// see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
106-
webpackConfig
107-
.plugin('split-vendor-async')
108-
.use(CommonsChunkPlugin, [{
109-
name: 'app',
110-
async: 'vendor-async',
111-
children: true,
112-
minChunks: 3
113-
}])
114-
11593
// DLL
11694
if (options.dll) {
11795
const webpack = require('webpack')
@@ -142,15 +120,6 @@ module.exports = (api, options) => {
142120
}])
143121
.after('preload')
144122
}
145-
146-
// copy static assets in public/
147-
webpackConfig
148-
.plugin('copy')
149-
.use(require('copy-webpack-plugin'), [[{
150-
from: api.resolve('public'),
151-
to: api.resolve(options.outputDir),
152-
ignore: ['index.html', '.DS_Store']
153-
}]])
154123
}
155124
})
156125
}

packages/@vue/cli-service/lib/config/base.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ module.exports = (api, options) => {
33
const resolveLocal = require('../util/resolveLocal')
44
const inlineLimit = 10000
55

6+
webpackConfig
7+
.set('mode', 'development')
8+
69
webpackConfig
710
.context(api.service.context)
811
.entry('app')

packages/@vue/cli-service/lib/config/css.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ module.exports = (api, options) => {
101101
})
102102
}
103103

104+
// TODO: this is emitting useless css chunks with webpack 4 + async chunks
105+
104106
// inject CSS extraction plugin
105107
if (extract) {
106108
const userOptions = options.extractCSS && typeof options.extractCSS === 'object'
@@ -113,8 +115,5 @@ module.exports = (api, options) => {
113115
allChunks: true
114116
}, userOptions)])
115117
}
116-
117-
// TODO document receipe for using css.loaderOptions to add `data` option
118-
// to sass-loader
119118
})
120119
}

packages/@vue/cli-service/lib/config/dev.js

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,16 @@ module.exports = api => {
1010
.plugin('hmr')
1111
.use(require('webpack/lib/HotModuleReplacementPlugin'))
1212

13-
webpackConfig
14-
.plugin('named-modules')
15-
.use(require('webpack/lib/NamedModulesPlugin'))
16-
1713
webpackConfig
1814
.plugin('no-emit-on-errors')
1915
.use(require('webpack/lib/NoEmitOnErrorsPlugin'))
2016

21-
webpackConfig
22-
.plugin('watch-missing')
23-
.use(
24-
require('../webpack/WatchMissingNodeModulesPlugin'),
25-
[api.resolve('node_modules')]
26-
)
17+
// webpackConfig
18+
// .plugin('watch-missing')
19+
// .use(
20+
// require('../webpack/WatchMissingNodeModulesPlugin'),
21+
// [api.resolve('node_modules')]
22+
// )
2723
}
2824
})
2925
}
Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
module.exports = (api, options) => {
22
api.chainWebpack(webpackConfig => {
33
if (process.env.NODE_ENV === 'production') {
4+
webpackConfig
5+
.set('mode', 'production')
6+
47
webpackConfig
58
.devtool('source-map')
69
.output
@@ -12,11 +15,6 @@ module.exports = (api, options) => {
1215
.plugin('hash-module-ids')
1316
.use(require('webpack/lib/HashedModuleIdsPlugin'))
1417

15-
// enable scope hoisting / tree shaking
16-
webpackConfig
17-
.plugin('module-concatenation')
18-
.use(require('webpack/lib/optimize/ModuleConcatenationPlugin'))
19-
2018
// optimize CSS (dedupe)
2119
webpackConfig
2220
.plugin('optimize-css')
@@ -27,14 +25,17 @@ module.exports = (api, options) => {
2725
}])
2826

2927
// minify JS
30-
const UglifyPlugin = require('uglifyjs-webpack-plugin')
31-
const getUglifyOptions = require('./uglifyOptions')
32-
// disable during tests to speed things up
33-
if (!process.env.VUE_CLI_TEST) {
34-
webpackConfig
35-
.plugin('uglify')
36-
.use(UglifyPlugin, [getUglifyOptions(options)])
37-
}
28+
webpackConfig.optimization.set('minimizer', [{
29+
apply: compiler => {
30+
// disable during tests to speed things up
31+
if (process.env.VUE_CLI_TEST) {
32+
return
33+
}
34+
const UglifyPlugin = require('uglifyjs-webpack-plugin')
35+
const getUglifyOptions = require('./uglifyOptions')
36+
new UglifyPlugin(getUglifyOptions(options)).apply(compiler)
37+
}
38+
}])
3839
}
3940
})
4041
}

packages/@vue/cli-service/lib/webpack/InlineSourcePlugin.js

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,13 @@ module.exports = class InlineSourcePlugin {
1818

1919
apply (compiler) {
2020
// Hook into the html-webpack-plugin processing
21-
compiler.plugin('compilation', compilation => {
22-
compilation.plugin('html-webpack-plugin-before-html-generation', (htmlPluginData, callback) => {
23-
callback(null, htmlPluginData)
24-
})
25-
compilation.plugin('html-webpack-plugin-alter-asset-tags', (htmlPluginData, callback) => {
21+
compiler.hooks.compilation.tap('InlineSourcePlugin', compilation => {
22+
compilation.hooks.htmlWebpackPluginAlterAssetTags.tap('InlineSourcePlugin', htmlPluginData => {
2623
if (!this.options.include) {
27-
return callback(null, htmlPluginData)
24+
return htmlPluginData
2825
}
2926
const regex = this.options.include
30-
const result = this.processTags(compilation, regex, htmlPluginData)
31-
callback(null, result)
27+
return this.processTags(compilation, regex, htmlPluginData)
3228
})
3329
})
3430
}

packages/@vue/cli-service/lib/webpack/PreloadPlugin.js

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,14 @@ const doesChunkBelongToHTML = (chunk, roots, visitedChunks) => {
3434
}
3535
}
3636

37-
for (const parent of chunk.parents) {
38-
if (doesChunkBelongToHTML(parent, roots, visitedChunks)) {
39-
return true
40-
}
41-
}
37+
// TODO: this does not work with webpack 4
38+
// also prefetch doesn't seem to work at all
39+
40+
// for (const parent of chunk.parents) {
41+
// if (doesChunkBelongToHTML(parent, roots, visitedChunks)) {
42+
// return true
43+
// }
44+
// }
4245

4346
return false
4447
}
@@ -56,20 +59,19 @@ module.exports = class PreloadPlugin {
5659

5760
apply (compiler) {
5861
const options = this.options
59-
compiler.plugin('compilation', compilation => {
62+
compiler.hooks.compilation.tap('PreloadPlugin', compilation => {
6063
// Auto DLL plugin injects assets by mutating html plugin data, so the only
6164
// way to get a hold of those is by saving the pre-mutated assets and
6265
// comparing them later.
6366
let originalAssets
64-
compilation.plugin('html-webpack-plugin-before-html-generation', (htmlPluginData, cb) => {
67+
compilation.hooks.htmlWebpackPluginBeforeHtmlGeneration.tap('PreloadPlugin', htmlPluginData => {
6568
originalAssets = [
6669
...htmlPluginData.assets.js,
6770
...htmlPluginData.assets.css
6871
]
69-
cb(null, htmlPluginData)
7072
})
7173

72-
compilation.plugin('html-webpack-plugin-before-html-processing', (htmlPluginData, cb) => {
74+
compilation.hooks.htmlWebpackPluginBeforeHtmlProcessing.tap('PreloadPlugin', htmlPluginData => {
7375
let filesToInclude = ''
7476
let extractedChunks = []
7577
// 'asyncChunks' are chunks intended for lazy/async loading usually generated as
@@ -78,13 +80,13 @@ module.exports = class PreloadPlugin {
7880
// configured to preload all types of chunks or just prefetch chunks as needed.
7981
if (options.include === undefined || options.include === 'asyncChunks') {
8082
try {
81-
extractedChunks = compilation.chunks.filter(chunk => !chunk.isInitial())
83+
extractedChunks = compilation.chunks.filter(chunk => !chunk.isOnlyInitial())
8284
} catch (e) {
8385
extractedChunks = compilation.chunks
8486
}
8587
} else if (options.include === 'initial') {
8688
try {
87-
extractedChunks = compilation.chunks.filter(chunk => chunk.isInitial())
89+
extractedChunks = compilation.chunks.filter(chunk => chunk.isOnlyInitial())
8890
} catch (e) {
8991
extractedChunks = compilation.chunks
9092
}
@@ -155,7 +157,7 @@ module.exports = class PreloadPlugin {
155157
// Otherwise assume at least a <body> is present and update it to include a new <head>
156158
htmlPluginData.html = htmlPluginData.html.replace('<body>', '<head>' + filesToInclude + '</head><body>')
157159
}
158-
cb(null, htmlPluginData)
160+
return htmlPluginData
159161
})
160162
})
161163
}

packages/@vue/cli-service/lib/webpack/TimeFixPlugin.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,11 @@ module.exports = class TimeFixPlugin {
44
}
55

66
apply (compiler) {
7-
compiler.plugin('watch-run', (watching, callback) => {
7+
compiler.hooks.watchRun.tap('TimeFixPlugin', watching => {
88
watching.startTime += this.timefix
9-
callback()
109
})
1110

12-
compiler.plugin('done', stats => {
11+
compiler.hooks.done.tap('TimeFixPlugin', stats => {
1312
stats.startTime -= this.timefix
1413
})
1514
}

0 commit comments

Comments
 (0)