feat: upgrade to webpack 4

BREAKING CHANGE: Upgrade wepback 4, all webpack option
modifications must be webpcak 4 compatible. Drop support
for webpack plugins that do not work with v4 or above.
This commit is contained in:
Evan You
2018-05-08 16:55:13 -04:00
parent 6d4e51dd18
commit 2dcdeddde4
28 changed files with 580 additions and 865 deletions

View File

@@ -49,7 +49,6 @@
"globby": "^8.0.1",
"http-server": "^0.11.1",
"jest": "^22.1.4",
"json-server": "^0.12.2",
"lerna": "^2.8.0",
"lint-staged": "^6.0.1",
"memfs": "^2.6.0",

View File

@@ -22,9 +22,9 @@
"access": "public"
},
"dependencies": {
"chromedriver": "^2.38.1",
"deepmerge": "^2.0.1",
"execa": "^0.9.0",
"chromedriver": "^2.38.3",
"deepmerge": "^2.1.0",
"execa": "^0.10.0",
"nightwatch": "^0.9.21",
"selenium-server": "^3.11.0"
}

View File

@@ -22,7 +22,7 @@
"access": "public"
},
"dependencies": {
"workbox-webpack-plugin": "^3.1.0"
"workbox-webpack-plugin": "^3.2.0"
},
"devDependencies": {
"register-service-worker": "^1.0.0"

View File

@@ -25,8 +25,8 @@
"@types/node": "^9.3.0",
"fork-ts-checker-webpack-plugin": "^0.4.1",
"globby": "^8.0.1",
"ts-loader": "^3.4.0",
"tslint": "^5.9.1",
"ts-loader": "^4.3.0",
"tslint": "^5.10.0",
"typescript": "^2.8.3"
},
"devDependencies": {

View File

@@ -22,7 +22,7 @@
"access": "public"
},
"dependencies": {
"execa": "^0.9.0",
"execa": "^0.10.0",
"jest": "^22.4.3",
"jest-serializer-vue": "^1.0.0",
"jest-transform-stub": "^1.0.0",

View File

@@ -21,11 +21,11 @@
},
"homepage": "https://github.com/vuejs/vue-cli/packages/@vue/cli-plugin-unit-mocha#readme",
"dependencies": {
"execa": "^0.9.0",
"jsdom": "^11.6.2",
"execa": "^0.10.0",
"jsdom": "^11.10.0",
"jsdom-global": "^3.0.2",
"mocha": "^4.1.0",
"mocha-webpack": "^1.1.0",
"mocha": "^5.1.1",
"mocha-webpack": "^2.0.0-beta.0",
"webpack-node-externals": "^1.7.2"
},
"devDependencies": {

View File

@@ -25,8 +25,8 @@
"@vue/cli-plugin-babel": "^3.0.0-beta.9",
"@vue/cli-plugin-eslint": "^3.0.0-beta.9",
"@vue/cli-service": "^3.0.0-beta.9",
"chalk": "^2.4.0",
"eslint-plugin-vue": "^4.3.0",
"chalk": "^2.4.1",
"eslint-plugin-vue": "^4.5.0",
"resolve": "^1.7.1",
"vue": "^2.5.16"
}

View File

@@ -25,12 +25,10 @@ test('build', async () => {
const index = await project.read('dist/index.html')
// should split and preload app.js & vendor.js
expect(index).toMatch(/<link rel=preload [^>]+app[^>]+\.js>/)
expect(index).toMatch(/<link rel=preload [^>]+vendor[^>]+\.js>/)
// should not preload manifest because it's inlined
expect(index).not.toMatch(/<link rel=preload [^>]+manifest[^>]+\.js>/)
// should inline manifest and webpack runtime
expect(index).toMatch('webpackJsonp')
expect(index).toMatch(/<link [^>]+js\/app[^>]+\.js rel=preload>/)
expect(index).toMatch(/<link [^>]+js\/vendors~app[^>]+\.js rel=preload>/)
// should preload css
expect(index).toMatch(/<link [^>]+app[^>]+\.css rel=preload>/)
const port = await portfinder.getPortPromise()
server = createServer({ root: path.join(project.dir, 'dist') })

View File

@@ -1,6 +1,7 @@
const Service = require('../lib/Service')
const LANGS = ['css', 'sass', 'scss', 'less', 'styl', 'stylus']
const extractLoaderPath = require('mini-css-extract-plugin').loader
const LOADERS = {
css: 'css',
@@ -36,7 +37,7 @@ const findLoaders = (config, lang) => {
const findOptions = (config, lang, _loader) => {
const rule = findRule(config, lang)
const use = rule.use.find(({ loader }) => loader.includes(`${_loader}-loader`))
return use.options
return use.options || {}
}
test('default loaders', () => {
@@ -58,10 +59,9 @@ test('default loaders', () => {
test('production defaults', () => {
const config = genConfig({ postcss: {}}, 'production')
const extractLoaderPath = require.resolve('extract-text-webpack-plugin/dist/loader')
LANGS.forEach(lang => {
const loader = lang === 'css' ? [] : LOADERS[lang]
expect(findLoaders(config, lang)).toEqual([extractLoaderPath, 'vue-style', 'css', 'postcss'].concat(loader))
expect(findLoaders(config, lang)).toEqual([extractLoaderPath, 'css', 'postcss'].concat(loader))
expect(findOptions(config, lang, 'css')).toEqual({
minimize: true,
sourceMap: false,
@@ -97,7 +97,6 @@ test('css.extract', () => {
}
}
}, 'production')
const extractLoaderPath = require.resolve('extract-text-webpack-plugin/dist/loader')
LANGS.forEach(lang => {
expect(findLoaders(config, lang)).not.toContain(extractLoaderPath)
})

View File

@@ -26,7 +26,7 @@ module.exports = (api, { entry, name }, options) => {
// only minify min entry
if (!/\.min/.test(postfix)) {
config.plugins.delete('uglify')
config.optimization.minimize(false)
}
// externalize Vue in case user imports it

View File

@@ -52,7 +52,7 @@ module.exports = (api, { target, entry, name }) => {
// only minify min entry
if (!minify) {
config.plugins.delete('uglify')
config.optimization.minimize(false)
}
// externalize Vue in case user imports it

View File

@@ -71,10 +71,6 @@ module.exports = (api, options) => {
// create compiler
const compiler = webpack(webpackConfig)
if (!process.env.VUE_CLI_TEST) {
compiler.apply(new webpack.ProgressPlugin())
}
// resolve server options
const useHttps = args.https || projectDevServerOptions.https || defaults.https
const host = args.host || process.env.HOST || projectDevServerOptions.host || defaults.host
@@ -148,7 +144,7 @@ module.exports = (api, options) => {
return new Promise((resolve, reject) => {
// log instructions & open browser on first compilation complete
let isFirstCompile = true
compiler.plugin('done', stats => {
compiler.hooks.done.tap('vue-cli-service serve', stats => {
if (stats.hasErrors()) {
return
}

View File

@@ -7,23 +7,6 @@ module.exports = (api, options) => {
return
}
// inject preload/prefetch to HTML
const PreloadPlugin = require('../webpack/PreloadPlugin')
webpackConfig
.plugin('preload')
.use(PreloadPlugin, [{
rel: 'preload',
include: 'initial',
fileBlacklist: [/\.map$/, /hot-update\.js$/]
}])
webpackConfig
.plugin('prefetch')
.use(PreloadPlugin, [{
rel: 'prefetch',
include: 'asyncChunks'
}])
// HTML plugin
const fs = require('fs')
const htmlPath = api.resolve('public/index.html')
@@ -38,6 +21,23 @@ module.exports = (api, options) => {
)
])
// inject preload/prefetch to HTML
const PreloadPlugin = require('preload-webpack-plugin')
webpackConfig
.plugin('preload')
.use(PreloadPlugin, [{
rel: 'preload',
include: 'initial',
fileBlacklist: [/\.map$/, /hot-update\.js$/]
}])
webpackConfig
.plugin('prefetch')
.use(PreloadPlugin, [{
rel: 'prefetch',
include: 'asyncChunks'
}])
// copy static assets in public/
webpackConfig
.plugin('copy')
@@ -63,61 +63,11 @@ module.exports = (api, options) => {
chunksSortMode: 'dependency'
})])
// Code splitting configs for better long-term caching
// This needs to be updated when upgrading to webpack 4
const CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin')
// extract vendor libs into its own chunk for better caching, since they
// are more likely to stay the same.
// code splitting
webpackConfig
.plugin('split-vendor')
.use(CommonsChunkPlugin, [{
name: 'vendor',
minChunks (module) {
// any required modules inside node_modules are extracted to vendor
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(`node_modules`) > -1
)
}
}])
// extract webpack runtime and module manifest to its own file in order to
// prevent vendor hash from being updated whenever app bundle is updated
webpackConfig
.plugin('split-manifest')
.use(CommonsChunkPlugin, [{
name: 'manifest',
minChunks: Infinity
}])
// inline the manifest chunk into HTML
webpackConfig
.plugin('inline-manifest')
.use(require('../webpack/InlineSourcePlugin'), [{
include: /manifest\..*\.js$/
}])
// since manifest is inlined, don't preload it anymore
webpackConfig
.plugin('preload')
.tap(([options]) => {
options.fileBlacklist.push(/manifest\..*\.js$/)
return [options]
})
// This CommonsChunkPlugin instance extracts shared chunks from async
// chunks and bundles them in a separate chunk, similar to the vendor chunk
// see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
webpackConfig
.plugin('split-vendor-async')
.use(CommonsChunkPlugin, [{
name: 'app',
async: 'vendor-async',
children: true,
minChunks: 3
}])
.optimization.splitChunks({
chunks: 'all'
})
}
})
}

View File

@@ -134,17 +134,13 @@ module.exports = (api, options) => {
resolveClientEnv(options.baseUrl)
])
webpackConfig
.plugin('timefix')
.use(require('../webpack/TimeFixPlugin'))
webpackConfig
.plugin('case-sensitive-paths')
.use(require('case-sensitive-paths-webpack-plugin'))
// friendly error plugin displays very confusing errors when webpack
// fails to resolve a loader, so we provide custom handlers to improve it
const { transformer, formatter } = require('../webpack/resolveLoaderError')
const { transformer, formatter } = require('../util/resolveLoaderError')
webpackConfig
.plugin('friendly-errors')
.use(require('friendly-errors-webpack-plugin'), [{

View File

@@ -24,7 +24,7 @@ module.exports = (api, options) => {
const shouldExtract = isProd && extract !== false && !shadowMode
const extractOptions = Object.assign({
filename: `css/[name].[contenthash:8].css`,
allChunks: true
chunkFilename: 'css/[name].[id].[contenthash:8].css'
}, extract && typeof extract === 'object' ? extract : {})
// check if the project has a valid postcss config
@@ -50,15 +50,17 @@ module.exports = (api, options) => {
if (shouldExtract) {
rule
.use('extract-css-loader')
.loader(require.resolve('extract-text-webpack-plugin/dist/loader'))
.options({ omit: 1, remove: true })
.loader(require('mini-css-extract-plugin').loader)
} else {
rule
.use('vue-style-loader')
.loader('vue-style-loader')
.options({
sourceMap,
shadowMode
})
}
rule.use('vue-style-loader').loader('vue-style-loader').options({
sourceMap,
shadowMode
})
const cssLoaderOptions = {
minimize: isProd,
sourceMap,
@@ -70,21 +72,23 @@ module.exports = (api, options) => {
localIdentName
})
}
rule.use('css-loader')
rule
.use('css-loader')
.loader('css-loader')
.options(cssLoaderOptions)
if (hasPostCSSConfig) {
rule.use('postcss-loader').loader('postcss-loader').options({
// TODO: use config value after https://github.com/postcss/postcss-loader/pull/361 is merged
sourceMap: true
})
rule
.use('postcss-loader')
.loader('postcss-loader')
.options({ sourceMap })
}
if (loader) {
rule.use(loader).loader(loader).options(Object.assign({
sourceMap
}, options))
rule
.use(loader)
.loader(loader)
.options(Object.assign({ sourceMap }, options))
}
}
}
@@ -103,7 +107,25 @@ module.exports = (api, options) => {
if (shouldExtract) {
webpackConfig
.plugin('extract-css')
.use(require('extract-text-webpack-plugin'), [extractOptions])
.use(require('mini-css-extract-plugin'), [extractOptions])
}
if (isProd) {
// optimize CSS (dedupe)
const cssProcessorOptions = {
safe: true,
autoprefixer: { disable: true },
mergeLonghand: false
}
if (options.productionSourceMap && options.cssSourceMap) {
cssProcessorOptions.map = { inline: false }
}
webpackConfig
.plugin('optimize-css')
.use(require('optimize-css-assets-webpack-plugin'), [{
canPrint: false,
cssProcessorOptions
}])
}
})
}

View File

@@ -1,6 +1,9 @@
module.exports = api => {
api.chainWebpack(webpackConfig => {
if (process.env.NODE_ENV === 'development') {
webpackConfig
.mode('development')
webpackConfig
.devtool('cheap-module-eval-source-map')
.output
@@ -18,12 +21,11 @@ module.exports = api => {
.plugin('no-emit-on-errors')
.use(require('webpack/lib/NoEmitOnErrorsPlugin'))
webpackConfig
.plugin('watch-missing')
.use(
require('../webpack/WatchMissingNodeModulesPlugin'),
[api.resolve('node_modules')]
)
if (!process.env.VUE_CLI_TEST) {
webpackConfig
.plugin('progress')
.use(require('webpack/lib/ProgressPlugin'))
}
}
})
}

View File

@@ -2,6 +2,7 @@ module.exports = (api, options) => {
api.chainWebpack(webpackConfig => {
if (process.env.NODE_ENV === 'production') {
webpackConfig
.mode('production')
.devtool('source-map')
.output
.filename(`js/[name].[chunkhash:8].js`)
@@ -12,28 +13,15 @@ module.exports = (api, options) => {
.plugin('hash-module-ids')
.use(require('webpack/lib/HashedModuleIdsPlugin'))
// enable scope hoisting / tree shaking
webpackConfig
.plugin('module-concatenation')
.use(require('webpack/lib/optimize/ModuleConcatenationPlugin'))
// optimize CSS (dedupe)
webpackConfig
.plugin('optimize-css')
.use(require('optimize-css-assets-webpack-plugin'), [{
cssProcessorOptions: options.productionSourceMap && options.cssSourceMap
? { safe: true, map: { inline: false }}
: { safe: true }
}])
// minify JS
const UglifyPlugin = require('uglifyjs-webpack-plugin')
const getUglifyOptions = require('./uglifyOptions')
// disable during tests to speed things up
if (!process.env.VUE_CLI_TEST) {
webpackConfig
.plugin('uglify')
.use(UglifyPlugin, [getUglifyOptions(options)])
// disable optimization during tests to speed things up
if (process.env.VUE_CLI_TEST) {
webpackConfig.optimization.minimize(false)
} else {
const UglifyPlugin = require('uglifyjs-webpack-plugin')
const uglifyOptions = require('./uglifyOptions')
webpackConfig.optimization.minimizer([
new UglifyPlugin(uglifyOptions(options))
])
}
}
})

View File

@@ -1,114 +0,0 @@
/*
The MIT License (MIT)
Copyright (c) 2016 Jan Nicklas
https://github.com/DustinJackson/html-webpack-inline-source-plugin/blob/master/LICENSE
Modified by Yuxi Evan You
*/
const path = require('path')
const slash = require('slash')
const sourceMapUrl = require('source-map-url')
const escapeRegex = require('escape-string-regexp')
module.exports = class InlineSourcePlugin {
constructor (options = {}) {
this.options = options
}
apply (compiler) {
// Hook into the html-webpack-plugin processing
compiler.plugin('compilation', compilation => {
compilation.plugin('html-webpack-plugin-before-html-generation', (htmlPluginData, callback) => {
callback(null, htmlPluginData)
})
compilation.plugin('html-webpack-plugin-alter-asset-tags', (htmlPluginData, callback) => {
if (!this.options.include) {
return callback(null, htmlPluginData)
}
const regex = this.options.include
const result = this.processTags(compilation, regex, htmlPluginData)
callback(null, result)
})
})
}
processTags (compilation, regex, pluginData) {
const processTag = tag => this.processTag(compilation, regex, tag)
return Object.assign({}, pluginData, {
head: pluginData.head.map(processTag),
body: pluginData.body.map(processTag)
})
}
processTag (compilation, regex, tag) {
let assetUrl
// inline js
if (tag.tagName === 'script' && regex.test(tag.attributes.src)) {
assetUrl = tag.attributes.src
tag = {
tagName: 'script',
closeTag: true,
attributes: {
type: 'text/javascript'
}
}
// inline css
} else if (tag.tagName === 'link' && regex.test(tag.attributes.href)) {
assetUrl = tag.attributes.href
tag = {
tagName: 'style',
closeTag: true,
attributes: {
type: 'text/css'
}
}
}
if (assetUrl) {
// Strip public URL prefix from asset URL to get Webpack asset name
const publicUrlPrefix = compilation.outputOptions.publicPath || ''
const assetName = path.posix.relative(publicUrlPrefix, assetUrl)
const asset = compilation.assets[assetName]
// do not emit inlined assets
delete compilation.assets[assetName]
const updatedSource = this.resolveSourceMaps(compilation, assetName, asset)
tag.innerHTML = (tag.tagName === 'script') ? updatedSource.replace(/(<)(\/script>)/g, '\\x3C$2') : updatedSource
}
return tag
}
resolveSourceMaps (compilation, assetName, asset) {
let source = asset.source()
const out = compilation.outputOptions
// Get asset file absolute path
const assetPath = path.join(out.path, assetName)
// Extract original sourcemap URL from source string
if (typeof source !== 'string') {
source = source.toString()
}
const mapUrlOriginal = sourceMapUrl.getFrom(source)
// Return unmodified source if map is unspecified, URL-encoded, or already relative to site root
if (!mapUrlOriginal || mapUrlOriginal.indexOf('data:') === 0 || mapUrlOriginal.indexOf('/') === 0) {
return source
}
// Figure out sourcemap file path *relative to the asset file path*
const assetDir = path.dirname(assetPath)
const mapPath = path.join(assetDir, mapUrlOriginal)
const mapPathRelative = path.relative(out.path, mapPath)
// Starting with Node 6, `path` module throws on `undefined`
const publicPath = out.publicPath || ''
// Prepend Webpack public URL path to source map relative path
// Calling `slash` converts Windows backslashes to forward slashes
const mapUrlCorrected = slash(path.join(publicPath, mapPathRelative))
// Regex: exact original sourcemap URL, possibly '*/' (for CSS), then EOF, ignoring whitespace
const regex = new RegExp(escapeRegex(mapUrlOriginal) + '(\\s*(?:\\*/)?\\s*$)')
// Replace sourcemap URL and (if necessary) preserve closing '*/' and whitespace
return source.replace(regex, (match, group) => {
return mapUrlCorrected + group
})
}
}

View File

@@ -1,162 +0,0 @@
/**
* @license
* Copyright 2017 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Modified by Yuxi Evan You
*/
const flatten = arr => arr.reduce((prev, curr) => prev.concat(curr), [])
const getValues = obj => Object.keys(obj).map(key => obj[key])
const doesChunkBelongToHTML = (chunk, roots, visitedChunks) => {
// Prevent circular recursion.
// See https://github.com/GoogleChromeLabs/preload-webpack-plugin/issues/49
if (visitedChunks[chunk.renderedHash]) {
return false
}
visitedChunks[chunk.renderedHash] = true
for (const root of roots) {
if (root.hash === chunk.renderedHash) {
return true
}
}
for (const parent of chunk.parents) {
if (doesChunkBelongToHTML(parent, roots, visitedChunks)) {
return true
}
}
return false
}
const defaultOptions = {
rel: 'preload',
include: 'asyncChunks',
fileBlacklist: [/\.map$/]
}
module.exports = class PreloadPlugin {
constructor (options) {
this.options = Object.assign({}, defaultOptions, options)
}
apply (compiler) {
const options = this.options
compiler.plugin('compilation', compilation => {
// Auto DLL plugin injects assets by mutating html plugin data, so the only
// way to get a hold of those is by saving the pre-mutated assets and
// comparing them later.
let originalAssets
compilation.plugin('html-webpack-plugin-before-html-generation', (htmlPluginData, cb) => {
originalAssets = [
...htmlPluginData.assets.js,
...htmlPluginData.assets.css
]
cb(null, htmlPluginData)
})
compilation.plugin('html-webpack-plugin-before-html-processing', (htmlPluginData, cb) => {
let filesToInclude = ''
let extractedChunks = []
// 'asyncChunks' are chunks intended for lazy/async loading usually generated as
// part of code-splitting with import() or require.ensure(). By default, asyncChunks
// get wired up using link rel=preload when using this plugin. This behaviour can be
// configured to preload all types of chunks or just prefetch chunks as needed.
if (options.include === undefined || options.include === 'asyncChunks') {
try {
extractedChunks = compilation.chunks.filter(chunk => !chunk.isInitial())
} catch (e) {
extractedChunks = compilation.chunks
}
} else if (options.include === 'initial') {
try {
extractedChunks = compilation.chunks.filter(chunk => chunk.isInitial())
} catch (e) {
extractedChunks = compilation.chunks
}
} else if (options.include === 'all') {
// Async chunks, vendor chunks, normal chunks.
extractedChunks = compilation.chunks
} else if (Array.isArray(options.include)) {
// Keep only user specified chunks
extractedChunks = compilation
.chunks
.filter((chunk) => {
const chunkName = chunk.name
// Works only for named chunks
if (!chunkName) {
return false
}
return options.include.indexOf(chunkName) > -1
})
}
const publicPath = compilation.outputOptions.publicPath || ''
// Only handle the chunk imported by the htmlWebpackPlugin
extractedChunks = extractedChunks.filter(chunk => doesChunkBelongToHTML(
chunk, getValues(htmlPluginData.assets.chunks), {}))
let files = flatten(extractedChunks.map(chunk => chunk.files))
// if handling initial or all chunks, also include assets injected by
// Auto DLL plugin.
if (options.include === 'initial' || options.include === 'all') {
files = [...htmlPluginData.assets.js, ...htmlPluginData.assets.css]
.filter(file => !originalAssets.includes(file))
.map(file => file.replace(publicPath, ''))
.concat(files)
}
Array.from(new Set(files)).filter(entry => {
return this.options.fileBlacklist.every(regex => regex.test(entry) === false)
}).forEach(entry => {
entry = `${publicPath}${entry}`
if (options.rel === 'preload') {
// If `as` value is not provided in option, dynamically determine the correct
// value depends on suffix of filename. Otherwise use the given `as` value.
let asValue
if (!options.as) {
if (entry.match(/\.css$/)) asValue = 'style'
else if (entry.match(/\.woff2$/)) asValue = 'font'
else asValue = 'script'
} else if (typeof options.as === 'function') {
asValue = options.as(entry)
} else {
asValue = options.as
}
const crossOrigin = asValue === 'font' ? 'crossorigin="crossorigin" ' : ''
filesToInclude += `<link rel="${options.rel}" as="${asValue}" ${crossOrigin}href="${entry}">\n`
} else {
// If preload isn't specified, the only other valid entry is prefetch here
// You could specify preconnect but as we're dealing with direct paths to resources
// instead of origins that would make less sense.
filesToInclude += `<link rel="${options.rel}" href="${entry}">\n`
}
})
if (htmlPluginData.html.indexOf('</head>') !== -1) {
// If a valid closing </head> is found, update it to include preload/prefetch tags
htmlPluginData.html = htmlPluginData.html.replace('</head>', filesToInclude + '</head>')
} else {
// Otherwise assume at least a <body> is present and update it to include a new <head>
htmlPluginData.html = htmlPluginData.html.replace('<body>', '<head>' + filesToInclude + '</head><body>')
}
cb(null, htmlPluginData)
})
})
}
}

View File

@@ -1,16 +0,0 @@
module.exports = class TimeFixPlugin {
constructor (timefix = 11000) {
this.timefix = timefix
}
apply (compiler) {
compiler.plugin('watch-run', (watching, callback) => {
watching.startTime += this.timefix
callback()
})
compiler.plugin('done', stats => {
stats.startTime -= this.timefix
})
}
}

View File

@@ -1,32 +0,0 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file at
* https://github.com/facebookincubator/create-react-app/blob/master/LICENSE
*/
// This Webpack plugin ensures `npm install <library>` forces a project rebuild.
// Were not sure why this isn't Webpack's default behavior.
// See https://github.com/facebookincubator/create-react-app/issues/186.
module.exports = class WatchMissingNodeModulesPlugin {
constructor (nodeModulesPath) {
this.nodeModulesPath = nodeModulesPath
}
apply (compiler) {
compiler.plugin('emit', (compilation, callback) => {
var missingDeps = compilation.missingDependencies
var nodeModulesPath = this.nodeModulesPath
// If any missing files are expected to appear in node_modules...
if (missingDeps.some(file => file.indexOf(nodeModulesPath) !== -1)) {
// ...tell webpack to watch node_modules recursively until they appear.
compilation.contextDependencies.push(nodeModulesPath)
}
callback()
})
}
}

View File

@@ -25,17 +25,16 @@
"@vue/cli-shared-utils": "^3.0.0-beta.9",
"@vue/web-component-wrapper": "^1.2.0",
"address": "^1.0.3",
"autoprefixer": "^8.3.0",
"autoprefixer": "^8.4.1",
"cache-loader": "^1.2.2",
"case-sensitive-paths-webpack-plugin": "^2.1.2",
"chalk": "^2.4.0",
"chalk": "^2.4.1",
"cliui": "^4.1.0",
"copy-webpack-plugin": "^4.5.1",
"css-loader": "^0.28.11",
"escape-string-regexp": "^1.0.5",
"extract-text-webpack-plugin": "^3.0.2",
"file-loader": "^1.1.11",
"friendly-errors-webpack-plugin": "^1.6.1",
"friendly-errors-webpack-plugin": "^1.7.0",
"fs-extra": "^6.0.0",
"get-value": "^3.0.1",
"globby": "^8.0.1",
@@ -43,11 +42,13 @@
"javascript-stringify": "^1.6.0",
"launch-editor-middleware": "^2.2.1",
"lodash.defaultsdeep": "^4.6.0",
"mini-css-extract-plugin": "^0.4.0",
"minimist": "^1.2.0",
"optimize-css-assets-webpack-plugin": "^3.2.0",
"ora": "^2.0.0",
"optimize-css-assets-webpack-plugin": "^4.0.1",
"ora": "^2.1.0",
"portfinder": "^1.0.13",
"postcss-loader": "^2.1.1",
"postcss-loader": "^2.1.5",
"preload-webpack-plugin": "^3.0.0-alpha.1",
"read-pkg": "^3.0.0",
"semver": "^5.5.0",
"slash": "^2.0.0",
@@ -58,9 +59,9 @@
"url-loader": "^1.0.1",
"vue-loader": "^15.0.9",
"vue-template-compiler": "^2.5.16",
"webpack": "^3.10.0",
"webpack": "^4.8.1",
"webpack-chain": "^4.6.0",
"webpack-dev-server": "^2.11.1",
"webpack-dev-server": "^3.1.4",
"webpack-merge": "^4.1.2",
"yorkie": "^1.0.3"
},

View File

@@ -21,7 +21,8 @@
"access": "public"
},
"dependencies": {
"execa": "^0.8.0",
"execa": "^0.10.0",
"json-server": "^0.12.2",
"puppeteer": "^1.0.0",
"strip-ansi": "^3.0.0"
}

View File

@@ -22,7 +22,7 @@
"homepage": "https://github.com/vuejs/vue-cli/packages/@vue/eslint-config-airbnb#readme",
"dependencies": {
"eslint-config-airbnb-base": "^12.1.0",
"eslint-import-resolver-webpack": "^0.8.4",
"eslint-import-resolver-webpack": "^0.9.0",
"eslint-plugin-import": "^2.11.0"
}
}

View File

@@ -21,8 +21,8 @@
},
"homepage": "https://github.com/vuejs/vue-cli/packages/@vue/eslint-config-standard#readme",
"dependencies": {
"eslint-config-standard": "^11.0.0",
"eslint-plugin-import": "^2.9.0",
"eslint-config-standard": "^12.0.0-alpha.0",
"eslint-plugin-import": "^2.11.0",
"eslint-plugin-node": "^6.0.1",
"eslint-plugin-promise": "^3.7.0",
"eslint-plugin-standard": "^3.1.0"

View File

@@ -21,7 +21,7 @@
},
"homepage": "https://github.com/vuejs/vue-cli/packages/@vue/eslint-config-typescript#readme",
"dependencies": {
"eslint-plugin-typescript": "^0.11.0",
"eslint-plugin-typescript": "^0.12.0",
"typescript-eslint-parser": "^15.0.0"
}
}

837
yarn.lock

File diff suppressed because it is too large Load Diff