chore: merge dev

This commit is contained in:
Evan You
2018-05-28 22:10:41 -04:00
19 changed files with 439 additions and 12334 deletions

View File

@@ -42,7 +42,7 @@ beforeAll(async () => {
test('dep from node_modules should not been transpiled', async () => {
const { stdout } = await project.run('vue-cli-service build')
let $vendorjs = stdout.match(/(js\/vendors~app\.[^.]+\.js)/)[1]
let $vendorjs = stdout.match(/(js\/chunk-vendors\.[^.]+\.js)/)[1]
$vendorjs = `dist/${$vendorjs}`
$vendorjs = await project.read($vendorjs)
@@ -58,7 +58,7 @@ test('dep from node_modules should been transpiled', async () => {
const { stdout } = await project.run('vue-cli-service build')
let $vendorjs = stdout.match(/(js\/vendors~app\.[^.]+\.js)/)[1]
let $vendorjs = stdout.match(/(js\/chunk-vendors\.[^.]+\.js)/)[1]
$vendorjs = `dist/${$vendorjs}`
$vendorjs = await project.read($vendorjs)

View File

@@ -1,7 +1,27 @@
module.exports = (api, { lintOnSave }) => {
if (lintOnSave) {
module.exports = (api, options) => {
if (options.lintOnSave) {
const extensions = require('./eslintOptions').extensions(api)
const cacheIdentifier = genCacheIdentifier(api.resolve('.'))
// eslint-loader doesn't bust cache when eslint config changes
// so we have to manually generate a cache identifier that takes the config
// into account.
const { genCacheConfig } = require('@vue/cli-shared-utils')
const { cacheIdentifier } = genCacheConfig(
api,
options,
[
'eslint-loader',
'eslint'
],
[
'.eslintrc.js',
'.eslintrc.yaml',
'.eslintrc.yml',
'.eslintrc.json',
'.eslintrc',
'package.json'
]
)
api.chainWebpack(webpackConfig => {
webpackConfig.module
@@ -18,7 +38,7 @@ module.exports = (api, { lintOnSave }) => {
extensions,
cache: true,
cacheIdentifier,
emitWarning: lintOnSave !== 'error',
emitWarning: options.lintOnSave !== 'error',
formatter: require('eslint/lib/formatters/codeframe')
})
})
@@ -38,33 +58,3 @@ module.exports = (api, { lintOnSave }) => {
require('./lint')(args, api)
})
}
// eslint-loader doesn't bust cache when eslint config changes
// so we have to manually generate a cache identifier that takes the config
// into account.
function genCacheIdentifier (context) {
const fs = require('fs')
const path = require('path')
const files = [
'.eslintrc.js',
'.eslintrc.yaml',
'.eslintrc.yml',
'.eslintrc.json',
'.eslintrc',
'package.json'
]
const configTimeStamp = (() => {
for (const file of files) {
if (fs.existsSync(path.join(context, file))) {
return fs.statSync(file).mtimeMs
}
}
})()
return JSON.stringify({
'eslint-loader': require('eslint-loader/package.json').version,
'eslint': require('eslint/package.json').version,
'config': configTimeStamp
})
}

View File

@@ -31,7 +31,7 @@ test('pwa', async () => {
// should split and preload app.js & vendor.js
expect(index).toMatch(/<link [^>]+js\/app[^>]+\.js rel=preload>/)
expect(index).toMatch(/<link [^>]+js\/vendors~app[^>]+\.js rel=preload>/)
expect(index).toMatch(/<link [^>]+js\/chunk-vendors[^>]+\.js rel=preload>/)
// should preload css
expect(index).toMatch(/<link [^>]+app[^>]+\.css rel=preload>/)

View File

@@ -41,7 +41,7 @@ module.exports = (api, options) => {
loader: 'ts-loader',
options: {
transpileOnly: true,
appendTsSuffixTo: [/\.vue$/],
appendTsSuffixTo: ['\\.vue$'],
// https://github.com/TypeStrong/ts-loader#happypackmode-boolean-defaultfalse
happyPackMode: useThreads
}
@@ -50,7 +50,7 @@ module.exports = (api, options) => {
tsxRule.use('ts-loader').loader('ts-loader').tap(options => {
options = Object.assign({}, options)
delete options.appendTsSuffixTo
options.appendTsxSuffixTo = [/\.vue$/]
options.appendTsxSuffixTo = ['\\.vue$']
return options
})

View File

@@ -26,7 +26,7 @@ test('build', async () => {
const index = await project.read('dist/index.html')
// should split and preload app.js & vendor.js
expect(index).toMatch(/<link [^>]+js\/app[^>]+\.js rel=preload>/)
expect(index).toMatch(/<link [^>]+js\/vendors~app[^>]+\.js rel=preload>/)
expect(index).toMatch(/<link [^>]+js\/chunk-vendors[^>]+\.js rel=preload>/)
// should preload css
expect(index).toMatch(/<link [^>]+app[^>]+\.css rel=preload>/)

View File

@@ -22,12 +22,15 @@ const genConfig = (pkg = {}, env) => {
return config
}
const findRule = (config, lang, index = 2) => {
const findRule = (config, lang, index = 3) => {
const baseRule = config.module.rules.find(rule => {
return rule.test.test(`.${lang}`)
})
// all CSS rules have oneOf with two child rules, one for <style lang="module">
// and one for normal imports
// all CSS rules have 4 oneOf rules:
// - <style lang="module"> in Vue files
// - <style> in Vue files
// - *.modules.css imports from JS
// - *.css imports from JS
return baseRule.oneOf[index]
}
@@ -76,7 +79,13 @@ test('production defaults', () => {
})
test('CSS Modules rules', () => {
const config = genConfig()
const config = genConfig({
vue: {
css: {
modules: true
}
}
})
LANGS.forEach(lang => {
const expected = {
importLoaders: lang === 'css' ? 1 : 2, // no postcss-loader
@@ -85,10 +94,12 @@ test('CSS Modules rules', () => {
sourceMap: false,
modules: true
}
// module-query rules
// vue-modules rules
expect(findOptions(config, lang, 'css', 0)).toEqual(expected)
// module-ext rules
expect(findOptions(config, lang, 'css', 1)).toEqual(expected)
// normal-modules rules
expect(findOptions(config, lang, 'css', 2)).toEqual(expected)
// normal rules
expect(findOptions(config, lang, 'css', 3)).toEqual(expected)
})
})

View File

@@ -0,0 +1,170 @@
jest.setTimeout(30000)
const path = require('path')
const portfinder = require('portfinder')
const { defaultPreset } = require('@vue/cli/lib/options')
const { createServer } = require('http-server')
const create = require('@vue/cli-test-utils/createTestProject')
const serve = require('@vue/cli-test-utils/serveWithPuppeteer')
const launchPuppeteer = require('@vue/cli-test-utils/launchPuppeteer')
async function makeProjectMultiPage (project) {
await project.write('vue.config.js', `
module.exports = {
pages: {
index: { entry: 'src/main.js' },
foo: { entry: 'src/foo.js' },
bar: { entry: 'src/bar.js' }
},
chainWebpack: config => {
const splitOptions = config.optimization.get('splitChunks')
config.optimization.splitChunks(Object.assign({}, splitOptions, {
minSize: 10000
}))
}
}
`)
await project.write('src/foo.js', `
import Vue from 'vue'
new Vue({
el: '#app',
render: h => h('h1', 'Foo')
})
`)
await project.write('src/bar.js', `
import Vue from 'vue'
import App from './App.vue'
new Vue({
el: '#app',
render: h => h(App)
})
`)
const app = await project.read('src/App.vue')
await project.write('src/App.vue', app.replace(
`import HelloWorld from './components/HelloWorld.vue'`,
`const HelloWorld = () => import('./components/HelloWorld.vue')`
))
}
test('serve w/ multi page', async () => {
const project = await create('e2e-multi-page-serve', defaultPreset)
await makeProjectMultiPage(project)
await serve(
() => project.run('vue-cli-service serve'),
async ({ page, url, helpers }) => {
expect(await helpers.getText('h1')).toMatch(`Welcome to Your Vue.js App`)
await page.goto(`${url}/foo.html`)
expect(await helpers.getText('h1')).toMatch(`Foo`)
await page.goto(`${url}/bar.html`)
expect(await helpers.getText('h1')).toMatch(`Welcome to Your Vue.js App`)
}
)
})
let server, browser, page
test('build w/ multi page', async () => {
const project = await create('e2e-multi-page-build', defaultPreset)
await makeProjectMultiPage(project)
const { stdout } = await project.run('vue-cli-service build')
expect(stdout).toMatch('Build complete.')
// should generate the HTML pages
expect(project.has('dist/index.html')).toBe(true)
expect(project.has('dist/foo.html')).toBe(true)
expect(project.has('dist/bar.html')).toBe(true)
const assertSharedAssets = file => {
// should split and preload vendor chunk
expect(file).toMatch(/<link [^>]+js\/chunk-vendors[^>]+\.js rel=preload>/)
// should split and preload common js and css
expect(file).toMatch(/<link [^>]+js\/chunk-common[^>]+\.js rel=preload>/)
expect(file).toMatch(/<link [^>]+chunk-common[^>]+\.css rel=preload>/)
// should load common css
expect(file).toMatch(/<link href=\/css\/chunk-common\.\w+\.css rel=stylesheet>/)
// should load common js
expect(file).toMatch(/<script [^>]+src=\/js\/chunk-vendors\.\w+\.js>/)
expect(file).toMatch(/<script [^>]+src=\/js\/chunk-common\.\w+\.js>/)
}
const index = await project.read('dist/index.html')
assertSharedAssets(index)
// should preload correct page file
expect(index).toMatch(/<link [^>]+js\/index[^>]+\.js rel=preload>/)
expect(index).not.toMatch(/<link [^>]+js\/foo[^>]+\.js rel=preload>/)
expect(index).not.toMatch(/<link [^>]+js\/bar[^>]+\.js rel=preload>/)
// should prefetch async chunk js and css
expect(index).toMatch(/<link [^>]+css\/0\.\w+\.css rel=prefetch>/)
expect(index).toMatch(/<link [^>]+js\/0\.\w+\.js rel=prefetch>/)
// should load correct page js
expect(index).toMatch(/<script [^>]+src=\/js\/index\.\w+\.js>/)
expect(index).not.toMatch(/<script [^>]+src=\/js\/foo\.\w+\.js>/)
expect(index).not.toMatch(/<script [^>]+src=\/js\/bar\.\w+\.js>/)
const foo = await project.read('dist/foo.html')
assertSharedAssets(foo)
// should preload correct page file
expect(foo).not.toMatch(/<link [^>]+js\/index[^>]+\.js rel=preload>/)
expect(foo).toMatch(/<link [^>]+js\/foo[^>]+\.js rel=preload>/)
expect(foo).not.toMatch(/<link [^>]+js\/bar[^>]+\.js rel=preload>/)
// should not prefetch async chunk js and css because it's not used by
// this entry
expect(foo).not.toMatch(/<link [^>]+css\/0\.\w+\.css rel=prefetch>/)
expect(foo).not.toMatch(/<link [^>]+js\/0\.\w+\.js rel=prefetch>/)
// should load correct page js
expect(foo).not.toMatch(/<script [^>]+src=\/js\/index\.\w+\.js>/)
expect(foo).toMatch(/<script [^>]+src=\/js\/foo\.\w+\.js>/)
expect(foo).not.toMatch(/<script [^>]+src=\/js\/bar\.\w+\.js>/)
const bar = await project.read('dist/bar.html')
assertSharedAssets(bar)
// should preload correct page file
expect(bar).not.toMatch(/<link [^>]+js\/index[^>]+\.js rel=preload>/)
expect(bar).not.toMatch(/<link [^>]+js\/foo[^>]+\.js rel=preload>/)
expect(bar).toMatch(/<link [^>]+js\/bar[^>]+\.js rel=preload>/)
// should prefetch async chunk js and css
expect(bar).toMatch(/<link [^>]+css\/0\.\w+\.css rel=prefetch>/)
expect(bar).toMatch(/<link [^>]+js\/0\.\w+\.js rel=prefetch>/)
// should load correct page js
expect(bar).not.toMatch(/<script [^>]+src=\/js\/index\.\w+\.js>/)
expect(bar).not.toMatch(/<script [^>]+src=\/js\/foo\.\w+\.js>/)
expect(bar).toMatch(/<script [^>]+src=\/js\/bar\.\w+\.js>/)
// assert pages work
const port = await portfinder.getPortPromise()
server = createServer({ root: path.join(project.dir, 'dist') })
await new Promise((resolve, reject) => {
server.listen(port, err => {
if (err) return reject(err)
resolve()
})
})
const url = `http://localhost:${port}/`
const launched = await launchPuppeteer(url)
browser = launched.browser
page = launched.page
const getH1Text = async () => page.evaluate(() => {
return document.querySelector('h1').textContent
})
expect(await getH1Text()).toMatch('Welcome to Your Vue.js App')
await page.goto(`${url}foo.html`)
expect(await getH1Text()).toMatch('Foo')
await page.goto(`${url}bar.html`)
expect(await getH1Text()).toMatch('Welcome to Your Vue.js App')
})
afterAll(async () => {
await browser.close()
server.close()
})

View File

@@ -1,5 +1,7 @@
jest.setTimeout(45000)
jest.setTimeout(60000)
const path = require('path')
const fs = require('fs-extra')
const { defaultPreset } = require('@vue/cli/lib/options')
const create = require('@vue/cli-test-utils/createTestProject')
const serve = require('@vue/cli-test-utils/serveWithPuppeteer')
@@ -50,8 +52,6 @@ test('serve with router', async () => {
test('serve with inline entry', async () => {
const project = await create('e2e-serve-inline-entry', defaultPreset)
const path = require('path')
const fs = require('fs-extra')
await fs.move(
path.resolve(project.dir, 'src/main.js'),
path.resolve(project.dir, 'src/index.js')
@@ -72,3 +72,24 @@ test('serve with inline entry', async () => {
}
)
})
test('serve with no public dir', async () => {
const project = await create('e2e-serve-no-public', defaultPreset)
await fs.remove(path.resolve(project.dir, 'public'))
await serve(
() => project.run('vue-cli-service serve'),
async ({ nextUpdate, helpers }) => {
const msg = `Welcome to Your Vue.js App`
expect(await helpers.getText('h1')).toMatch(msg)
// test hot reload
const file = await project.read(`src/App.vue`)
project.write(`src/App.vue`, file.replace(msg, `Updated`))
await nextUpdate() // wait for child stdout update signal
await sleep(1000) // give the client time to update
expect(await helpers.getText('h1')).toMatch(`Updated`)
}
)
})

View File

@@ -59,7 +59,7 @@ module.exports = (api, options) => {
// respect inline build destination in copy plugin
if (args.dest) {
api.chainWebpack(config => {
if (args.target === 'app') {
if (config.plugins.has('copy')) {
config.plugin('copy').tap(args => {
args[0][0].to = targetDir
return args

View File

@@ -31,7 +31,7 @@ module.exports = (api, { entry, name }, options) => {
const config = api.resolveChainableWebpackConfig()
// adjust css output name so they write to the same file
if (options.css.extract !== false) {
if (config.plugins.has('extract-css')) {
config
.plugin('extract-css')
.tap(args => {

View File

@@ -1,4 +1,6 @@
// config that are specific to --target app
const fs = require('fs')
const path = require('path')
module.exports = (api, options) => {
api.chainWebpack(webpackConfig => {
@@ -7,8 +9,11 @@ module.exports = (api, options) => {
return
}
const isProd = process.env.NODE_ENV === 'production'
// HTML plugin
const resolveClientEnv = require('../util/resolveClientEnv')
const htmlOptions = {
templateParameters: (compilation, assets, pluginOptions) => {
// enhance html-webpack-plugin's built in template params
@@ -27,62 +32,135 @@ module.exports = (api, options) => {
}, resolveClientEnv(options.baseUrl, true /* raw */))
}
}
// only set template path if index.html exists
const htmlPath = api.resolve('public/index.html')
if (require('fs').existsSync(htmlPath)) {
htmlOptions.template = htmlPath
if (isProd) {
Object.assign(htmlOptions, {
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
// more options:
// https://github.com/kangax/html-minifier#options-quick-reference
},
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
chunksSortMode: 'dependency'
})
}
webpackConfig
.plugin('html')
.use(require('html-webpack-plugin'), [htmlOptions])
// resolve HTML file(s)
const HTMLPlugin = require('html-webpack-plugin')
const PreloadPlugin = require('@vue/preload-webpack-plugin')
const multiPageConfig = options.pages
const htmlPath = api.resolve('public/index.html')
const defaultHtmlPath = path.resolve(__dirname, 'index-default.html')
// 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$/]
}])
if (!multiPageConfig) {
// default, single page setup.
htmlOptions.template = fs.existsSync(htmlPath)
? htmlPath
: defaultHtmlPath
webpackConfig
.plugin('prefetch')
.use(PreloadPlugin, [{
rel: 'prefetch',
include: 'asyncChunks'
}])
// copy static assets in public/
webpackConfig
.plugin('copy')
.use(require('copy-webpack-plugin'), [[{
from: api.resolve('public'),
to: api.resolve(options.outputDir),
ignore: ['index.html', '.DS_Store']
}]])
if (process.env.NODE_ENV === 'production') {
// minify HTML
webpackConfig
.plugin('html')
.tap(([options]) => [Object.assign(options, {
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
// more options:
// https://github.com/kangax/html-minifier#options-quick-reference
},
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
chunksSortMode: 'dependency'
})])
.use(HTMLPlugin, [htmlOptions])
// code splitting
// inject preload/prefetch to HTML
webpackConfig
.plugin('preload')
.use(PreloadPlugin, [{
rel: 'preload',
include: 'initial',
fileBlacklist: [/\.map$/, /hot-update\.js$/]
}])
webpackConfig
.plugin('prefetch')
.use(PreloadPlugin, [{
rel: 'prefetch',
include: 'asyncChunks'
}])
} else {
// multi-page setup
webpackConfig.entryPoints.clear()
const pages = Object.keys(multiPageConfig)
pages.forEach(name => {
const {
entry,
template = `public/${name}.html`,
filename = `${name}.html`
} = multiPageConfig[name]
// inject entry
webpackConfig.entry(name).add(api.resolve(entry))
// inject html plugin for the page
const pageHtmlOptions = Object.assign({}, htmlOptions, {
chunks: ['chunk-vendors', 'chunk-common', name],
template: fs.existsSync(template) ? template : defaultHtmlPath,
filename
})
webpackConfig
.plugin(`html-${name}`)
.use(HTMLPlugin, [pageHtmlOptions])
})
pages.forEach(name => {
const { filename = `${name}.html` } = multiPageConfig[name]
webpackConfig
.plugin(`preload-${name}`)
.use(PreloadPlugin, [{
rel: 'preload',
includeHtmlNames: [filename],
include: {
type: 'initial',
entries: [name]
},
fileBlacklist: [/\.map$/, /hot-update\.js$/]
}])
webpackConfig
.plugin(`prefetch-${name}`)
.use(PreloadPlugin, [{
rel: 'prefetch',
includeHtmlNames: [filename],
include: {
type: 'asyncChunks',
entries: [name]
}
}])
})
}
// copy static assets in public/
if (fs.existsSync(api.resolve('public'))) {
webpackConfig
.plugin('copy')
.use(require('copy-webpack-plugin'), [[{
from: api.resolve('public'),
to: api.resolve(options.outputDir),
ignore: ['index.html', '.DS_Store']
}]])
}
// code splitting
if (isProd) {
webpackConfig
.optimization.splitChunks({
chunks: 'all'
chunks: 'all',
name: (m, chunks, cacheGroup) => `chunk-${cacheGroup}`,
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
},
common: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
})
}
})

View File

@@ -26,7 +26,12 @@ module.exports = (api, options) => {
.end()
.alias
.set('@', api.resolve('src'))
.set('vue$', options.compiler ? 'vue/dist/vue.esm.js' : 'vue/dist/vue.runtime.esm.js')
.set(
'vue$',
options.runtimeCompiler
? 'vue/dist/vue.esm.js'
: 'vue/dist/vue.runtime.esm.js'
)
webpackConfig.resolveLoader
.set('symlinks', true)

View File

@@ -14,6 +14,7 @@ module.exports = (api, options) => {
const getAssetPath = require('../util/getAssetPath')
const {
modules = false,
extract = true,
sourceMap = false,
localIdentName = '[name]_[local]_[hash:base64:5]',
@@ -25,7 +26,7 @@ module.exports = (api, options) => {
const shouldExtract = isProd && extract !== false && !shadowMode
const extractOptions = Object.assign({
filename: getAssetPath(options, `css/[name].[contenthash:8].css`),
chunkFilename: getAssetPath(options, 'css/[name].[id].[contenthash:8].css')
chunkFilename: getAssetPath(options, 'css/[name].[contenthash:8].css')
}, extract && typeof extract === 'object' ? extract : {})
// check if the project has a valid postcss config
@@ -43,15 +44,20 @@ module.exports = (api, options) => {
const baseRule = webpackConfig.module.rule(lang).test(test)
// rules for <style lang="module">
const modulesRule = baseRule.oneOf('modules-query').resourceQuery(/module/)
applyLoaders(modulesRule, true)
const vueModulesRule = baseRule.oneOf('vue-modules').resourceQuery(/module/)
applyLoaders(vueModulesRule, true)
// rules for <style>
const vueNormalRule = baseRule.oneOf('vue').resourceQuery(/\?vue/)
applyLoaders(vueNormalRule, false)
// rules for *.module.* files
const modulesExtRule = baseRule.oneOf('modules-ext').test(/\.module\.\w+$/)
applyLoaders(modulesExtRule, true)
const extModulesRule = baseRule.oneOf('normal-modules').test(/\.module\.\w+$/)
applyLoaders(extModulesRule, true)
// rules for normal CSS imports
const normalRule = baseRule.oneOf('normal')
applyLoaders(normalRule, false)
applyLoaders(normalRule, modules)
function applyLoaders (rule, modules) {
if (shouldExtract) {

View File

@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>Vue App</title>
</head>
<body>
<div id="app"></div>
</body>
</html>

View File

@@ -5,14 +5,16 @@ const schema = createSchema(joi => joi.object({
devBaseUrl: joi.string(),
outputDir: joi.string(),
assetsDir: joi.string(),
compiler: joi.boolean(),
runtimeCompiler: joi.boolean(),
transpileDependencies: joi.array(),
productionSourceMap: joi.boolean(),
parallel: joi.boolean(),
devServer: joi.object(),
pages: joi.object(),
// css
css: joi.object({
modules: joi.boolean(),
localIdentName: joi.string(),
extract: joi.alternatives().try(joi.boolean(), joi.object()),
sourceMap: joi.boolean(),
@@ -65,8 +67,12 @@ exports.defaults = () => ({
// enabled by default if the machine has more than 1 cores
parallel: require('os').cpus().length > 1,
// multi-page config
pages: undefined,
css: {
// extract: true,
// modules: false,
// localIdentName: '[name]_[local]_[hash:base64:5]',
// sourceMap: false,
// loaderOptions: {}

View File

@@ -23,6 +23,7 @@
"dependencies": {
"@vue/cli-overlay": "^3.0.0-beta.11",
"@vue/cli-shared-utils": "^3.0.0-beta.11",
"@vue/preload-webpack-plugin": "^1.0.0",
"@vue/web-component-wrapper": "^1.2.0",
"acorn": "^5.5.3",
"address": "^1.0.3",
@@ -50,7 +51,6 @@
"ora": "^2.1.0",
"portfinder": "^1.0.13",
"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",

View File

@@ -1,25 +1,44 @@
const fs = require('fs')
const path = require('path')
const hash = require('hash-sum')
exports.genCacheConfig = (api, options, id, configFile) => {
const cacheDirectory = process.env.VUE_CLI_TEST
? path.resolve(__dirname, `../../../../node_modules/.cache/${id}`)
: api.resolve(`node_modules/.cache/${id}`)
exports.genCacheConfig = (api, options, deps, configFiles) => {
if (!Array.isArray(deps)) {
deps = [deps]
}
const id = deps[0]
const cacheDirectory = api.resolve(`node_modules/.cache/${id}`)
const variables = {
[id]: require(`${id}/package.json`).version,
'cache-loader': require('cache-loader/package.json').version,
env: process.env.NODE_ENV,
test: !!process.env.VUE_CLI_TEST,
config: (options.chainWebpack || '').toString() + (options.configureWebpack || '').toString()
config: [options.chainWebpack, options.configureWebpack]
}
if (configFile) {
const file = api.resolve(configFile)
if (fs.existsSync(file)) {
variables.configFile = fs.readFileSync(configFile, 'utf-8')
for (const dep of deps) {
variables[dep] = require(`${dep}/package.json`).version
}
const readConfig = file => {
const absolutePath = api.resolve(file)
if (fs.existsSync(absolutePath)) {
return fs.readFileSync(absolutePath, 'utf-8')
}
}
const cacheIdentifier = JSON.stringify(variables)
if (configFiles) {
if (!Array.isArray(configFiles)) {
configFiles = [configFiles]
}
for (const file of configFiles) {
const content = readConfig(file)
if (content) {
variables.configFiles = content
break
}
}
}
const cacheIdentifier = hash(variables)
return { cacheDirectory, cacheIdentifier }
}

View File

@@ -22,6 +22,7 @@
"chalk": "^2.3.0",
"cmd-shim": "^2.0.2",
"execa": "^0.10.0",
"hash-sum": "^1.0.2",
"joi": "^12.0.0",
"node-ipc": "^9.1.1",
"opn": "^5.2.0",

12214
yarn.lock

File diff suppressed because it is too large Load Diff