Skip to content

Commit

Permalink
feat: upgrade to vue-loader 15
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
yyx990803 committed May 4, 2018
1 parent 8dbe262 commit f5c0f58
Show file tree
Hide file tree
Showing 12 changed files with 126 additions and 333 deletions.
22 changes: 0 additions & 22 deletions packages/@vue/cli-plugin-babel/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,27 +42,5 @@ module.exports = (api, {
jsRule
.use('babel-loader')
.loader('babel-loader')

webpackConfig.module
.rule('vue')
.use('vue-loader')
.tap(options => {
options.loaders = options.loaders || {}
options.loaders.js = [
{
loader: 'cache-loader',
options: { cacheDirectory }
}
]
if (useThreads) {
options.loaders.js.push({
loader: 'thread-loader'
})
}
options.loaders.js.push({
loader: 'babel-loader'
})
return options
})
})
}
1 change: 1 addition & 0 deletions packages/@vue/cli-plugin-eslint/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ module.exports = (api, { lintOnSave }) => {
.pre()
.exclude
.add(/node_modules/)
.add(require('path').dirname(require.resolve('@vue/cli-service')))
.end()
.test(/\.(vue|(j|t)sx?)$/)
.use('eslint-loader')
Expand Down
45 changes: 11 additions & 34 deletions packages/@vue/cli-plugin-typescript/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,42 +16,13 @@ module.exports = (api, {
.extensions
.merge(['.ts', '.tsx'])

const tsRule = config.module
.rule('ts')
.test(/\.tsx?$/)

const vueLoader = config.module
.rule('vue')
.use('vue-loader')
const tsRule = config.module.rule('ts').test(/\.ts$/)
const tsxRule = config.module.rule('tsx').test(/\.tsx$/)

// add a loader to both *.ts & vue<lang="ts">
const addLoader = loader => {
const use = tsRule
.use(loader.loader)
.loader(loader.loader)
if (loader.options) {
use.options(loader.options)
}
vueLoader.tap(options => {
options.loaders = options.loaders || {}
options.loaders.ts = options.loaders.ts || []
options.loaders.ts.push(loader)
options.loaders.tsx = options.loaders.tsx || []
if (loader.loader === 'ts-loader') {
// for TSX need to append tsx suffix
options.loaders.tsx.push({
loader: 'ts-loader',
options: {
transpileOnly: true,
appendTsxSuffixTo: [/\.vue$/],
happyPackMode: useThreads
}
})
} else {
options.loaders.tsx.push(loader)
}
return options
})
const addLoader = ({ loader, options }) => {
tsRule.use(loader).loader(loader).options(options)
tsxRule.use(loader).loader(loader).options(options)
}

addLoader({
Expand Down Expand Up @@ -79,6 +50,12 @@ module.exports = (api, {
happyPackMode: useThreads
}
})
// make sure to append TSX suffix
tsxRule.use('ts-loader').loader('ts-loader').tap(options => {
delete options.appendTsSuffixTo
options.appendTsxSuffixTo = [/\.vue$/]
return options
})
} else {
// Experimental: compile TS with babel so that it can leverage
// preset-env for auto-detected polyfills based on browserslists config.
Expand Down
9 changes: 0 additions & 9 deletions packages/@vue/cli-service-global/lib/globalConfigPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,6 @@ module.exports = function createConfigPlugin (context, entry, asLib) {
presets: [require.resolve('@vue/babel-preset-app')]
}

// set inline vue-loader options
config.module
.rule('vue')
.use('vue-loader')
.tap(options => {
options.loaders.js[1].options = babelOptions
return options
})

// set inline babel options
config.module
.rule('js')
Expand Down
55 changes: 15 additions & 40 deletions packages/@vue/cli-service/__tests__/css.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,14 @@ const genConfig = (pkg = {}, env) => {
}

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

const findLoaders = (config, lang) => {
const rule = findRule(config, lang)
if (!rule) {
throw new Error(`rule not found for ${lang}`)
}
return rule.use.map(({ loader }) => loader.replace(/-loader$/, ''))
}

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

const findUsesForVue = (config, lang) => {
const vueOptions = findOptions(config, 'vue', 'vue')
return vueOptions.loaders[lang]
}

const findLoadersForVue = (config, lang) => {
return findUsesForVue(config, lang).map(({ loader }) => loader.replace(/-loader$/, ''))
}

const findOptionsForVue = (config, lang, _loader) => {
const uses = findUsesForVue(config, lang)
const use = uses.find(({ loader }) => `${_loader}-loader` === loader)
return use.options
}

const expectedCssLoaderModulesOptions = {
importLoaders: 1,
localIdentName: `[name]_[local]__[hash:base64:5]`,
minimize: false,
sourceMap: false,
modules: true
}

test('default loaders', () => {
const config = genConfig({ postcss: {}})

LANGS.forEach(lang => {
const loader = lang === 'css' ? [] : LOADERS[lang]
expect(findLoaders(config, lang)).toEqual(['vue-style', 'css', 'postcss'].concat(loader))
// vue-loader loaders should not include postcss because it's built-in
expect(findLoadersForVue(config, lang)).toEqual(['vue-style', 'css'].concat(loader))
// assert css-loader options
expect(findOptions(config, lang, 'css')).toEqual({
minimize: false,
sourceMap: false
sourceMap: false,
importLoaders: lang === 'css' ? 1 : 2
})
// files ending in .module.lang
expect(findOptions(config, `module.${lang}`, 'css')).toEqual(expectedCssLoaderModulesOptions)
})

// sass indented syntax
expect(findOptions(config, 'sass', 'sass')).toEqual({ indentedSyntax: true, sourceMap: false })
expect(findOptionsForVue(config, 'sass', 'sass')).toEqual({ indentedSyntax: true, sourceMap: false })
})

test('production defaults', () => {
Expand All @@ -88,10 +62,10 @@ test('production defaults', () => {
LANGS.forEach(lang => {
const loader = lang === 'css' ? [] : LOADERS[lang]
expect(findLoaders(config, lang)).toEqual([extractLoaderPath, 'vue-style', 'css', 'postcss'].concat(loader))
expect(findLoadersForVue(config, lang)).toEqual([extractLoaderPath, 'vue-style', 'css'].concat(loader))
expect(findOptions(config, lang, 'css')).toEqual({
minimize: true,
sourceMap: false
sourceMap: false,
importLoaders: lang === 'css' ? 1 : 2
})
})
})
Expand All @@ -105,7 +79,13 @@ test('css.modules', () => {
}
})
LANGS.forEach(lang => {
expect(findOptions(config, lang, 'css')).toEqual(expectedCssLoaderModulesOptions)
expect(findOptions(config, lang, 'css')).toEqual({
importLoaders: lang === 'css' ? 0 : 1, // no postcss-loader
localIdentName: `[name]_[local]_[hash:base64:5]`,
minimize: false,
sourceMap: false,
modules: true
})
})
})

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

Expand All @@ -137,8 +116,6 @@ test('css.sourceMap', () => {
expect(findOptions(config, lang, 'css').sourceMap).toBe(true)
expect(findOptions(config, lang, 'postcss').sourceMap).toBe(true)
expect(findOptions(config, lang, LOADERS[lang]).sourceMap).toBe(true)
expect(findOptionsForVue(config, lang, 'css').sourceMap).toBe(true)
expect(findOptionsForVue(config, lang, LOADERS[lang]).sourceMap).toBe(true)
})
})

Expand Down Expand Up @@ -172,9 +149,7 @@ test('css.loaderOptions', () => {
})

expect(findOptions(config, 'scss', 'sass')).toEqual({ data, sourceMap: false })
expect(findOptionsForVue(config, 'scss', 'sass')).toEqual({ data, sourceMap: false })
expect(findOptions(config, 'sass', 'sass')).toEqual({ data, indentedSyntax: true, sourceMap: false })
expect(findOptionsForVue(config, 'sass', 'sass')).toEqual({ data, indentedSyntax: true, sourceMap: false })
})

test('skip postcss-loader if no postcss config found', () => {
Expand Down
5 changes: 3 additions & 2 deletions packages/@vue/cli-service/lib/commands/build/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,13 @@ module.exports = (api, options) => {
} = require('@vue/cli-shared-utils')

log()
const mode = api.service.mode
if (args.target === 'app') {
logWithSpinner(`Building for ${args.mode}...`)
logWithSpinner(`Building for ${mode}...`)
} else {
const buildMode = buildModes[args.target]
if (buildMode) {
logWithSpinner(`Building for ${args.mode} as ${buildMode}...`)
logWithSpinner(`Building for ${mode} as ${buildMode}...`)
} else {
throw new Error(`Unknown build target: ${args.target}`)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ const createElement = (prefix, component, file, async) => {
const { camelName, kebabName } = exports.fileToComponentName(prefix, component)

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

Expand Down Expand Up @@ -52,7 +52,7 @@ import wrap from '@vue/web-component-wrapper'
// runtime shared by every component chunk
import 'css-loader/lib/css-base'
import 'vue-style-loader/lib/addStylesShadow'
import 'vue-loader/lib/runtime/component-normalizer'
import 'vue-loader/lib/runtime/componentNormalizer'
;(() => {
let i
Expand Down
27 changes: 25 additions & 2 deletions packages/@vue/cli-service/lib/config/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,26 @@ module.exports = (api, options) => {
webpackConfig.module
.noParse(/^(vue|vue-router|vuex|vuex-router-sync)$/)

// js is handled by cli-plugin-bable
// js is handled by cli-plugin-bable ---------------------------------------

// vue-loader --------------------------------------------------------------

webpackConfig.module
.rule('vue')
.test(/\.vue$/)
.use('vue-loader')
.loader('vue-loader')
.options(Object.assign({}, options.vueLoader))
.options({
compilerOpitons: {
preserveWhitespace: false
}
})

webpackConfig
.plugin('vue-loader')
.use(require('vue-loader/lib/plugin'))

// static assets -----------------------------------------------------------

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

// Other common pre-processors ---------------------------------------------

webpackConfig.module
.rule('pug')
.test(/\.pug$/)
.use('pug-plain-loader')
.loader('pug-plain-loader')
.end()

// shims

webpackConfig.node
.merge({
// prevent webpack from injecting useless setImmediate polyfill because Vue
Expand Down
Loading

0 comments on commit f5c0f58

Please sign in to comment.