Skip to content

Commit f5c0f58

Browse files
committed
feat: upgrade to vue-loader 15
BREAKING CHANGE: the "vueLoader" option has been removed. To modify vue-loader options, use chainWebpack then `config.module.rule(vue).use(vue-loader).tap()`. vue-loader has been upgraded to v15 and expects different options from v14.
1 parent 8dbe262 commit f5c0f58

File tree

12 files changed

+126
-333
lines changed

12 files changed

+126
-333
lines changed

packages/@vue/cli-plugin-babel/index.js

-22
Original file line numberDiff line numberDiff line change
@@ -42,27 +42,5 @@ module.exports = (api, {
4242
jsRule
4343
.use('babel-loader')
4444
.loader('babel-loader')
45-
46-
webpackConfig.module
47-
.rule('vue')
48-
.use('vue-loader')
49-
.tap(options => {
50-
options.loaders = options.loaders || {}
51-
options.loaders.js = [
52-
{
53-
loader: 'cache-loader',
54-
options: { cacheDirectory }
55-
}
56-
]
57-
if (useThreads) {
58-
options.loaders.js.push({
59-
loader: 'thread-loader'
60-
})
61-
}
62-
options.loaders.js.push({
63-
loader: 'babel-loader'
64-
})
65-
return options
66-
})
6745
})
6846
}

packages/@vue/cli-plugin-eslint/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ module.exports = (api, { lintOnSave }) => {
77
.pre()
88
.exclude
99
.add(/node_modules/)
10+
.add(require('path').dirname(require.resolve('@vue/cli-service')))
1011
.end()
1112
.test(/\.(vue|(j|t)sx?)$/)
1213
.use('eslint-loader')

packages/@vue/cli-plugin-typescript/index.js

+11-34
Original file line numberDiff line numberDiff line change
@@ -16,42 +16,13 @@ module.exports = (api, {
1616
.extensions
1717
.merge(['.ts', '.tsx'])
1818

19-
const tsRule = config.module
20-
.rule('ts')
21-
.test(/\.tsx?$/)
22-
23-
const vueLoader = config.module
24-
.rule('vue')
25-
.use('vue-loader')
19+
const tsRule = config.module.rule('ts').test(/\.ts$/)
20+
const tsxRule = config.module.rule('tsx').test(/\.tsx$/)
2621

2722
// add a loader to both *.ts & vue<lang="ts">
28-
const addLoader = loader => {
29-
const use = tsRule
30-
.use(loader.loader)
31-
.loader(loader.loader)
32-
if (loader.options) {
33-
use.options(loader.options)
34-
}
35-
vueLoader.tap(options => {
36-
options.loaders = options.loaders || {}
37-
options.loaders.ts = options.loaders.ts || []
38-
options.loaders.ts.push(loader)
39-
options.loaders.tsx = options.loaders.tsx || []
40-
if (loader.loader === 'ts-loader') {
41-
// for TSX need to append tsx suffix
42-
options.loaders.tsx.push({
43-
loader: 'ts-loader',
44-
options: {
45-
transpileOnly: true,
46-
appendTsxSuffixTo: [/\.vue$/],
47-
happyPackMode: useThreads
48-
}
49-
})
50-
} else {
51-
options.loaders.tsx.push(loader)
52-
}
53-
return options
54-
})
23+
const addLoader = ({ loader, options }) => {
24+
tsRule.use(loader).loader(loader).options(options)
25+
tsxRule.use(loader).loader(loader).options(options)
5526
}
5627

5728
addLoader({
@@ -79,6 +50,12 @@ module.exports = (api, {
7950
happyPackMode: useThreads
8051
}
8152
})
53+
// make sure to append TSX suffix
54+
tsxRule.use('ts-loader').loader('ts-loader').tap(options => {
55+
delete options.appendTsSuffixTo
56+
options.appendTsxSuffixTo = [/\.vue$/]
57+
return options
58+
})
8259
} else {
8360
// Experimental: compile TS with babel so that it can leverage
8461
// preset-env for auto-detected polyfills based on browserslists config.

packages/@vue/cli-service-global/lib/globalConfigPlugin.js

-9
Original file line numberDiff line numberDiff line change
@@ -60,15 +60,6 @@ module.exports = function createConfigPlugin (context, entry, asLib) {
6060
presets: [require.resolve('@vue/babel-preset-app')]
6161
}
6262

63-
// set inline vue-loader options
64-
config.module
65-
.rule('vue')
66-
.use('vue-loader')
67-
.tap(options => {
68-
options.loaders.js[1].options = babelOptions
69-
return options
70-
})
71-
7263
// set inline babel options
7364
config.module
7465
.rule('js')

packages/@vue/cli-service/__tests__/css.spec.js

+15-40
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,14 @@ const genConfig = (pkg = {}, env) => {
2222
}
2323

2424
const findRule = (config, lang) => config.module.rules.find(rule => {
25-
const test = rule.test.toString().replace(/\\/g, '')
26-
return test.indexOf(`${lang}$`) > -1
25+
return rule.test.test(`.${lang}`)
2726
})
2827

2928
const findLoaders = (config, lang) => {
3029
const rule = findRule(config, lang)
30+
if (!rule) {
31+
throw new Error(`rule not found for ${lang}`)
32+
}
3133
return rule.use.map(({ loader }) => loader.replace(/-loader$/, ''))
3234
}
3335

@@ -37,49 +39,21 @@ const findOptions = (config, lang, _loader) => {
3739
return use.options
3840
}
3941

40-
const findUsesForVue = (config, lang) => {
41-
const vueOptions = findOptions(config, 'vue', 'vue')
42-
return vueOptions.loaders[lang]
43-
}
44-
45-
const findLoadersForVue = (config, lang) => {
46-
return findUsesForVue(config, lang).map(({ loader }) => loader.replace(/-loader$/, ''))
47-
}
48-
49-
const findOptionsForVue = (config, lang, _loader) => {
50-
const uses = findUsesForVue(config, lang)
51-
const use = uses.find(({ loader }) => `${_loader}-loader` === loader)
52-
return use.options
53-
}
54-
55-
const expectedCssLoaderModulesOptions = {
56-
importLoaders: 1,
57-
localIdentName: `[name]_[local]__[hash:base64:5]`,
58-
minimize: false,
59-
sourceMap: false,
60-
modules: true
61-
}
62-
6342
test('default loaders', () => {
6443
const config = genConfig({ postcss: {}})
6544

6645
LANGS.forEach(lang => {
6746
const loader = lang === 'css' ? [] : LOADERS[lang]
6847
expect(findLoaders(config, lang)).toEqual(['vue-style', 'css', 'postcss'].concat(loader))
69-
// vue-loader loaders should not include postcss because it's built-in
70-
expect(findLoadersForVue(config, lang)).toEqual(['vue-style', 'css'].concat(loader))
7148
// assert css-loader options
7249
expect(findOptions(config, lang, 'css')).toEqual({
7350
minimize: false,
74-
sourceMap: false
51+
sourceMap: false,
52+
importLoaders: lang === 'css' ? 1 : 2
7553
})
76-
// files ending in .module.lang
77-
expect(findOptions(config, `module.${lang}`, 'css')).toEqual(expectedCssLoaderModulesOptions)
7854
})
79-
8055
// sass indented syntax
8156
expect(findOptions(config, 'sass', 'sass')).toEqual({ indentedSyntax: true, sourceMap: false })
82-
expect(findOptionsForVue(config, 'sass', 'sass')).toEqual({ indentedSyntax: true, sourceMap: false })
8357
})
8458

8559
test('production defaults', () => {
@@ -88,10 +62,10 @@ test('production defaults', () => {
8862
LANGS.forEach(lang => {
8963
const loader = lang === 'css' ? [] : LOADERS[lang]
9064
expect(findLoaders(config, lang)).toEqual([extractLoaderPath, 'vue-style', 'css', 'postcss'].concat(loader))
91-
expect(findLoadersForVue(config, lang)).toEqual([extractLoaderPath, 'vue-style', 'css'].concat(loader))
9265
expect(findOptions(config, lang, 'css')).toEqual({
9366
minimize: true,
94-
sourceMap: false
67+
sourceMap: false,
68+
importLoaders: lang === 'css' ? 1 : 2
9569
})
9670
})
9771
})
@@ -105,7 +79,13 @@ test('css.modules', () => {
10579
}
10680
})
10781
LANGS.forEach(lang => {
108-
expect(findOptions(config, lang, 'css')).toEqual(expectedCssLoaderModulesOptions)
82+
expect(findOptions(config, lang, 'css')).toEqual({
83+
importLoaders: lang === 'css' ? 0 : 1, // no postcss-loader
84+
localIdentName: `[name]_[local]_[hash:base64:5]`,
85+
minimize: false,
86+
sourceMap: false,
87+
modules: true
88+
})
10989
})
11090
})
11191

@@ -120,7 +100,6 @@ test('css.extract', () => {
120100
const extractLoaderPath = require.resolve('extract-text-webpack-plugin/dist/loader')
121101
LANGS.forEach(lang => {
122102
expect(findLoaders(config, lang)).not.toContain(extractLoaderPath)
123-
expect(findLoadersForVue(config, lang)).not.toContain(extractLoaderPath)
124103
})
125104
})
126105

@@ -137,8 +116,6 @@ test('css.sourceMap', () => {
137116
expect(findOptions(config, lang, 'css').sourceMap).toBe(true)
138117
expect(findOptions(config, lang, 'postcss').sourceMap).toBe(true)
139118
expect(findOptions(config, lang, LOADERS[lang]).sourceMap).toBe(true)
140-
expect(findOptionsForVue(config, lang, 'css').sourceMap).toBe(true)
141-
expect(findOptionsForVue(config, lang, LOADERS[lang]).sourceMap).toBe(true)
142119
})
143120
})
144121

@@ -172,9 +149,7 @@ test('css.loaderOptions', () => {
172149
})
173150

174151
expect(findOptions(config, 'scss', 'sass')).toEqual({ data, sourceMap: false })
175-
expect(findOptionsForVue(config, 'scss', 'sass')).toEqual({ data, sourceMap: false })
176152
expect(findOptions(config, 'sass', 'sass')).toEqual({ data, indentedSyntax: true, sourceMap: false })
177-
expect(findOptionsForVue(config, 'sass', 'sass')).toEqual({ data, indentedSyntax: true, sourceMap: false })
178153
})
179154

180155
test('skip postcss-loader if no postcss config found', () => {

packages/@vue/cli-service/lib/commands/build/index.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,13 @@ module.exports = (api, options) => {
4141
} = require('@vue/cli-shared-utils')
4242

4343
log()
44+
const mode = api.service.mode
4445
if (args.target === 'app') {
45-
logWithSpinner(`Building for ${args.mode}...`)
46+
logWithSpinner(`Building for ${mode}...`)
4647
} else {
4748
const buildMode = buildModes[args.target]
4849
if (buildMode) {
49-
logWithSpinner(`Building for ${args.mode} as ${buildMode}...`)
50+
logWithSpinner(`Building for ${mode} as ${buildMode}...`)
5051
} else {
5152
throw new Error(`Unknown build target: ${args.target}`)
5253
}

packages/@vue/cli-service/lib/commands/build/resolveWcEntry.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ const createElement = (prefix, component, file, async) => {
2222
const { camelName, kebabName } = exports.fileToComponentName(prefix, component)
2323

2424
return async
25-
? `window.customElements.define('${kebabName}', wrap(Vue, () => import('~root/${file}')))\n`
26-
: `import ${camelName} from '~root/${file}'\n` +
25+
? `window.customElements.define('${kebabName}', wrap(Vue, () => import('~root/${file}?shadow')))\n`
26+
: `import ${camelName} from '~root/${file}?shadow'\n` +
2727
`window.customElements.define('${kebabName}', wrap(Vue, ${camelName}))\n`
2828
}
2929

@@ -52,7 +52,7 @@ import wrap from '@vue/web-component-wrapper'
5252
// runtime shared by every component chunk
5353
import 'css-loader/lib/css-base'
5454
import 'vue-style-loader/lib/addStylesShadow'
55-
import 'vue-loader/lib/runtime/component-normalizer'
55+
import 'vue-loader/lib/runtime/componentNormalizer'
5656
5757
;(() => {
5858
let i

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

+25-2
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,26 @@ module.exports = (api, options) => {
3737
webpackConfig.module
3838
.noParse(/^(vue|vue-router|vuex|vuex-router-sync)$/)
3939

40-
// js is handled by cli-plugin-bable
40+
// js is handled by cli-plugin-bable ---------------------------------------
41+
42+
// vue-loader --------------------------------------------------------------
4143

4244
webpackConfig.module
4345
.rule('vue')
4446
.test(/\.vue$/)
4547
.use('vue-loader')
4648
.loader('vue-loader')
47-
.options(Object.assign({}, options.vueLoader))
49+
.options({
50+
compilerOpitons: {
51+
preserveWhitespace: false
52+
}
53+
})
54+
55+
webpackConfig
56+
.plugin('vue-loader')
57+
.use(require('vue-loader/lib/plugin'))
58+
59+
// static assets -----------------------------------------------------------
4860

4961
webpackConfig.module
5062
.rule('images')
@@ -87,6 +99,17 @@ module.exports = (api, options) => {
8799
name: `fonts/[name].[hash:8].[ext]`
88100
})
89101

102+
// Other common pre-processors ---------------------------------------------
103+
104+
webpackConfig.module
105+
.rule('pug')
106+
.test(/\.pug$/)
107+
.use('pug-plain-loader')
108+
.loader('pug-plain-loader')
109+
.end()
110+
111+
// shims
112+
90113
webpackConfig.node
91114
.merge({
92115
// prevent webpack from injecting useless setImmediate polyfill because Vue

0 commit comments

Comments
 (0)