mirror of
https://github.com/vuejs/vue-cli.git
synced 2026-04-21 20:08:41 -05:00
chore: merge dev
This commit is contained in:
@@ -24,4 +24,4 @@ Please see [contributing guide](https://github.com/vuejs/vue-cli/blob/dev/.githu
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
[MIT](https://github.com/vuejs/vue-cli/blob/dev/LICENSE)
|
||||
|
||||
@@ -21,11 +21,11 @@
|
||||
},
|
||||
"homepage": "https://github.com/vuejs/vue-cli/packages/@vue/babel-preset-app#readme",
|
||||
"dependencies": {
|
||||
"@babel/plugin-syntax-jsx": "7.0.0-beta.46",
|
||||
"@babel/plugin-transform-runtime": "7.0.0-beta.46",
|
||||
"@babel/preset-env": "7.0.0-beta.46",
|
||||
"@babel/preset-stage-2": "7.0.0-beta.46",
|
||||
"@babel/runtime": "7.0.0-beta.46",
|
||||
"@babel/plugin-syntax-jsx": "7.0.0-beta.47",
|
||||
"@babel/plugin-transform-runtime": "7.0.0-beta.47",
|
||||
"@babel/preset-env": "7.0.0-beta.47",
|
||||
"@babel/preset-stage-2": "7.0.0-beta.47",
|
||||
"@babel/runtime": "7.0.0-beta.47",
|
||||
"babel-helper-vue-jsx-merge-props": "^2.0.3",
|
||||
"babel-plugin-dynamic-import-node": "^1.2.0",
|
||||
"babel-plugin-transform-vue-jsx": "^4.0.1"
|
||||
|
||||
@@ -29,8 +29,7 @@ module.exports = {
|
||||
## Installing in an Already Created Project
|
||||
|
||||
``` sh
|
||||
npm install -D @vue/cli-plugin-babel
|
||||
vue invoke babel
|
||||
vue add @vue/babel
|
||||
```
|
||||
|
||||
## Injected webpack-chain Rules
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
jest.setTimeout(30000)
|
||||
|
||||
const { defaultPreset } = require('@vue/cli/lib/options')
|
||||
const create = require('@vue/cli-test-utils/createTestProject')
|
||||
|
||||
let project
|
||||
|
||||
beforeAll(async () => {
|
||||
project = await create('babel-transpile-deps', defaultPreset)
|
||||
|
||||
await project.write(
|
||||
'node_modules/external-dep/package.json',
|
||||
`{ "name": "external-dep", "version": "1.0.0", "main": "index.js" }`
|
||||
)
|
||||
|
||||
await project.write(
|
||||
'node_modules/external-dep/index.js',
|
||||
`const test = () => "__TEST__";\nexport default test`
|
||||
)
|
||||
|
||||
let $packageJson = await project.read('package.json')
|
||||
|
||||
$packageJson = JSON.parse($packageJson)
|
||||
$packageJson.dependencies['external-dep'] = '1.0.0'
|
||||
$packageJson = JSON.stringify($packageJson)
|
||||
|
||||
await project.write(
|
||||
'package.json',
|
||||
$packageJson
|
||||
)
|
||||
|
||||
let $mainjs = await project.read('src/main.js')
|
||||
|
||||
$mainjs = `import test from 'external-dep'\n${$mainjs}\nconsole.log(test())`
|
||||
|
||||
await project.write(
|
||||
'src/main.js',
|
||||
$mainjs
|
||||
)
|
||||
})
|
||||
|
||||
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]
|
||||
|
||||
$vendorjs = `dist/${$vendorjs}`
|
||||
$vendorjs = await project.read($vendorjs)
|
||||
|
||||
expect($vendorjs).toMatch('() => "__TEST__"')
|
||||
})
|
||||
|
||||
test('dep from node_modules should been transpiled', async () => {
|
||||
await project.write(
|
||||
'vue.config.js',
|
||||
`module.exports = { transpileDependencies: ['external-dep'] }`
|
||||
)
|
||||
|
||||
const { stdout } = await project.run('vue-cli-service build')
|
||||
|
||||
let $vendorjs = stdout.match(/(js\/vendors~app\.[^.]+\.js)/)[1]
|
||||
|
||||
$vendorjs = `dist/${$vendorjs}`
|
||||
$vendorjs = await project.read($vendorjs)
|
||||
|
||||
expect($vendorjs).toMatch('return "__TEST__"')
|
||||
})
|
||||
@@ -1,8 +1,3 @@
|
||||
// hack babel's codegen to fix source map.
|
||||
// this is a temporary patch before the actual change is released.
|
||||
// TODO remove after upgrading Babel to 7.0.0-beta.47
|
||||
require('./patchBabel')
|
||||
|
||||
module.exports = (api, {
|
||||
parallel,
|
||||
transpileDependencies
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
},
|
||||
"homepage": "https://github.com/vuejs/vue-cli/packages/@vue/cli-plugin-babel#readme",
|
||||
"dependencies": {
|
||||
"@babel/core": "7.0.0-beta.46",
|
||||
"@babel/core": "7.0.0-beta.47",
|
||||
"@vue/babel-preset-app": "^3.0.0-beta.10",
|
||||
"babel-loader": "^8.0.0-0"
|
||||
},
|
||||
|
||||
@@ -1,398 +0,0 @@
|
||||
/* eslint-disable */
|
||||
|
||||
const mod = require('@babel/core/lib/transformation/file/generate')
|
||||
|
||||
function _convertSourceMap () {
|
||||
var data = _interopRequireDefault(require('convert-source-map'))
|
||||
|
||||
_convertSourceMap = function _convertSourceMap () {
|
||||
return data
|
||||
}
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
function _generator () {
|
||||
var data = _interopRequireDefault(require('@babel/generator'))
|
||||
|
||||
_generator = function _generator () {
|
||||
return data
|
||||
}
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
function _interopRequireDefault (obj) { return obj && obj.__esModule ? obj : { default: obj } }
|
||||
|
||||
mod.default = function generateCode (pluginPasses, file) {
|
||||
var opts = file.opts,
|
||||
ast = file.ast,
|
||||
shebang = file.shebang,
|
||||
code = file.code,
|
||||
inputMap = file.inputMap
|
||||
var results = []
|
||||
|
||||
for (var _iterator = pluginPasses, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator](); ;) {
|
||||
var _ref
|
||||
|
||||
if (_isArray) {
|
||||
if (_i >= _iterator.length) break
|
||||
_ref = _iterator[_i++]
|
||||
} else {
|
||||
_i = _iterator.next()
|
||||
if (_i.done) break
|
||||
_ref = _i.value
|
||||
}
|
||||
|
||||
var plugins = _ref
|
||||
|
||||
for (var _iterator2 = plugins, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator](); ;) {
|
||||
var _ref2
|
||||
|
||||
if (_isArray2) {
|
||||
if (_i2 >= _iterator2.length) break
|
||||
_ref2 = _iterator2[_i2++]
|
||||
} else {
|
||||
_i2 = _iterator2.next()
|
||||
if (_i2.done) break
|
||||
_ref2 = _i2.value
|
||||
}
|
||||
|
||||
var plugin = _ref2
|
||||
var generatorOverride = plugin.generatorOverride
|
||||
|
||||
if (generatorOverride) {
|
||||
var _result2 = generatorOverride(ast, opts.generatorOpts, code, _generator().default)
|
||||
|
||||
if (_result2 !== undefined) results.push(_result2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var result
|
||||
|
||||
if (results.length === 0) {
|
||||
result = (0, _generator().default)(ast, opts.generatorOpts, code)
|
||||
} else if (results.length === 1) {
|
||||
result = results[0]
|
||||
|
||||
if (typeof result.then === 'function') {
|
||||
throw new Error('You appear to be using an async parser plugin, ' + 'which your current version of Babel does not support. ' + "If you're using a published plugin, " + 'you may need to upgrade your @babel/core version.')
|
||||
}
|
||||
} else {
|
||||
throw new Error('More than one plugin attempted to override codegen.')
|
||||
}
|
||||
|
||||
var _result = result,
|
||||
outputCode = _result.code,
|
||||
outputMap = _result.map
|
||||
|
||||
if (shebang) {
|
||||
outputCode = shebang + '\n' + outputCode
|
||||
}
|
||||
|
||||
if (outputMap && inputMap) {
|
||||
outputMap = mergeSourceMap(inputMap.toObject(), outputMap)
|
||||
}
|
||||
|
||||
if (opts.sourceMaps === 'inline' || opts.sourceMaps === 'both') {
|
||||
outputCode += '\n' + _convertSourceMap().default.fromObject(outputMap).toComment()
|
||||
}
|
||||
|
||||
if (opts.sourceMaps === 'inline') {
|
||||
outputMap = null
|
||||
}
|
||||
|
||||
return {
|
||||
outputCode: outputCode,
|
||||
outputMap: outputMap
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
const sourceMap = require('source-map')
|
||||
|
||||
function mergeSourceMap (
|
||||
inputMap,
|
||||
map,
|
||||
) {
|
||||
const input = buildMappingData(inputMap)
|
||||
const output = buildMappingData(map)
|
||||
|
||||
// Babel-generated maps always map to a single input filename.
|
||||
if (output.sources.length !== 1) {
|
||||
throw new Error('Assertion failure - expected a single output file')
|
||||
}
|
||||
const defaultSource = output.sources[0]
|
||||
|
||||
const mergedGenerator = new sourceMap.SourceMapGenerator()
|
||||
for (const { source } of input.sources) {
|
||||
if (typeof source.content === 'string') {
|
||||
mergedGenerator.setSourceContent(source.path, source.content)
|
||||
}
|
||||
}
|
||||
|
||||
const insertedMappings = new Map()
|
||||
|
||||
// Process each generated range in the input map, e.g. each range over the
|
||||
// code that Babel was originally given.
|
||||
eachInputGeneratedRange(input, (generated, original, source) => {
|
||||
// Then pick out each range over Babel's _output_ that corresponds with
|
||||
// the given range on the code given to Babel.
|
||||
eachOverlappingGeneratedOutputRange(defaultSource, generated, item => {
|
||||
// It's possible that multiple input ranges will overlap the same
|
||||
// generated range. Since sourcemap don't traditionally represent
|
||||
// generated locations with multiple original locations, we explicitly
|
||||
// skip generated locations once we've seen them the first time.
|
||||
const key = makeMappingKey(item)
|
||||
if (insertedMappings.has(key)) return
|
||||
insertedMappings.set(key, item)
|
||||
|
||||
mergedGenerator.addMapping({
|
||||
source: source.path,
|
||||
original: {
|
||||
line: original.line,
|
||||
column: original.columnStart
|
||||
},
|
||||
generated: {
|
||||
line: item.line,
|
||||
column: item.columnStart
|
||||
},
|
||||
name: original.name
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
// Since mappings are manipulated using single locations, but are interpreted
|
||||
// as ranges, the insertions above may not actually have their ending
|
||||
// locations mapped yet. Here be go through each one and ensure that it has
|
||||
// a well-defined ending location, if one wasn't already created by the start
|
||||
// of a different range.
|
||||
for (const item of insertedMappings.values()) {
|
||||
if (item.columnEnd === Infinity) {
|
||||
continue
|
||||
}
|
||||
|
||||
const clearItem = {
|
||||
line: item.line,
|
||||
columnStart: item.columnEnd
|
||||
}
|
||||
|
||||
const key = makeMappingKey(clearItem)
|
||||
if (insertedMappings.has(key)) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Insert mappings with no original position to terminate any mappings
|
||||
// that were found above, so that they don't expand beyond their correct
|
||||
// range.
|
||||
mergedGenerator.addMapping({
|
||||
generated: {
|
||||
line: clearItem.line,
|
||||
column: clearItem.columnStart
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const result = mergedGenerator.toJSON()
|
||||
// addMapping expects a relative path, and setSourceContent expects an
|
||||
// absolute path. To avoid this whole confusion, we leave the root out
|
||||
// entirely, and add it at the end here.
|
||||
if (typeof input.sourceRoot === 'string') {
|
||||
result.sourceRoot = input.sourceRoot
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
function makeMappingKey (item) {
|
||||
return JSON.stringify([item.line, item.columnStart])
|
||||
}
|
||||
|
||||
function eachOverlappingGeneratedOutputRange (
|
||||
outputFile,
|
||||
inputGeneratedRange,
|
||||
callback,
|
||||
) {
|
||||
// Find the Babel-generated mappings that overlap with this range in the
|
||||
// input sourcemap. Generated locations within the input sourcemap
|
||||
// correspond with the original locations in the map Babel generates.
|
||||
const overlappingOriginal = filterApplicableOriginalRanges(
|
||||
outputFile,
|
||||
inputGeneratedRange,
|
||||
)
|
||||
|
||||
for (const { generated } of overlappingOriginal) {
|
||||
for (const item of generated) {
|
||||
callback(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function filterApplicableOriginalRanges (
|
||||
{ mappings },
|
||||
{ line, columnStart, columnEnd },
|
||||
) {
|
||||
// The mapping array is sorted by original location, so we can
|
||||
// binary-search it for the overlapping ranges.
|
||||
return filterSortedArray(mappings, ({ original: outOriginal }) => {
|
||||
if (line > outOriginal.line) return -1
|
||||
if (line < outOriginal.line) return 1
|
||||
|
||||
if (columnStart >= outOriginal.columnEnd) return -1
|
||||
if (columnEnd <= outOriginal.columnStart) return 1
|
||||
|
||||
return 0
|
||||
})
|
||||
}
|
||||
|
||||
function eachInputGeneratedRange (
|
||||
map,
|
||||
callback
|
||||
|
||||
,
|
||||
) {
|
||||
for (const { source, mappings } of map.sources) {
|
||||
for (const { original, generated } of mappings) {
|
||||
for (const item of generated) {
|
||||
callback(item, original, source)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function buildMappingData (map) {
|
||||
const consumer = new sourceMap.SourceMapConsumer({
|
||||
...map,
|
||||
|
||||
// This is a bit hack. .addMapping expects source values to be relative,
|
||||
// but eachMapping returns mappings with absolute paths. To avoid that
|
||||
// incompatibility, we leave the sourceRoot out here and add it to the
|
||||
// final map at the end instead.
|
||||
sourceRoot: null
|
||||
})
|
||||
|
||||
const sources = new Map()
|
||||
const mappings = new Map()
|
||||
|
||||
let last = null
|
||||
|
||||
consumer.computeColumnSpans()
|
||||
|
||||
consumer.eachMapping(
|
||||
m => {
|
||||
if (m.originalLine === null) return
|
||||
|
||||
let source = sources.get(m.source)
|
||||
if (!source) {
|
||||
source = {
|
||||
path: m.source,
|
||||
content: consumer.sourceContentFor(m.source, true)
|
||||
}
|
||||
sources.set(m.source, source)
|
||||
}
|
||||
|
||||
let sourceData = mappings.get(source)
|
||||
if (!sourceData) {
|
||||
sourceData = {
|
||||
source,
|
||||
mappings: []
|
||||
}
|
||||
mappings.set(source, sourceData)
|
||||
}
|
||||
|
||||
const obj = {
|
||||
line: m.originalLine,
|
||||
columnStart: m.originalColumn,
|
||||
columnEnd: Infinity,
|
||||
name: m.name
|
||||
}
|
||||
|
||||
if (
|
||||
last &&
|
||||
last.source === source &&
|
||||
last.mapping.line === m.originalLine
|
||||
) {
|
||||
last.mapping.columnEnd = m.originalColumn
|
||||
}
|
||||
|
||||
last = {
|
||||
source,
|
||||
mapping: obj
|
||||
}
|
||||
|
||||
sourceData.mappings.push({
|
||||
original: obj,
|
||||
generated: consumer
|
||||
.allGeneratedPositionsFor({
|
||||
source: m.source,
|
||||
line: m.originalLine,
|
||||
column: m.originalColumn
|
||||
})
|
||||
.map(item => ({
|
||||
line: item.line,
|
||||
columnStart: item.column,
|
||||
// source-map's lastColumn is inclusive, not exclusive, so we need
|
||||
// to add 1 to it.
|
||||
columnEnd: item.lastColumn + 1
|
||||
}))
|
||||
})
|
||||
},
|
||||
null,
|
||||
sourceMap.SourceMapConsumer.ORIGINAL_ORDER,
|
||||
)
|
||||
|
||||
return {
|
||||
file: map.file,
|
||||
sourceRoot: map.sourceRoot,
|
||||
sources: Array.from(mappings.values())
|
||||
}
|
||||
}
|
||||
|
||||
function findInsertionLocation (
|
||||
array,
|
||||
callback,
|
||||
) {
|
||||
let left = 0
|
||||
let right = array.length
|
||||
while (left < right) {
|
||||
const mid = Math.floor((left + right) / 2)
|
||||
const item = array[mid]
|
||||
|
||||
const result = callback(item)
|
||||
if (result === 0) {
|
||||
left = mid
|
||||
break
|
||||
}
|
||||
if (result >= 0) {
|
||||
right = mid
|
||||
} else {
|
||||
left = mid + 1
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure the value is the start of any set of matches.
|
||||
let i = left
|
||||
if (i < array.length) {
|
||||
while (i > 0 && callback(array[i]) >= 0) {
|
||||
i--
|
||||
}
|
||||
return i + 1
|
||||
}
|
||||
|
||||
return i
|
||||
}
|
||||
|
||||
function filterSortedArray (
|
||||
array,
|
||||
callback,
|
||||
) {
|
||||
const start = findInsertionLocation(array, callback)
|
||||
|
||||
const results = []
|
||||
for (let i = start; i < array.length && callback(array[i]) === 0; i++) {
|
||||
results.push(array[i])
|
||||
}
|
||||
|
||||
return results
|
||||
}
|
||||
@@ -34,5 +34,5 @@ We've pre-configured Cypress to place most of the e2e testing related files unde
|
||||
## Installing in an Already Created Project
|
||||
|
||||
``` sh
|
||||
vue add e2e-cypress
|
||||
vue add @vue/e2e-cypress
|
||||
```
|
||||
|
||||
@@ -33,5 +33,5 @@ Consult Nightwatch docs for [configuration options](http://nightwatchjs.org/gett
|
||||
## Installing in an Already Created Project
|
||||
|
||||
``` sh
|
||||
vue add e2e-nightwatch
|
||||
vue add @vue/e2e-nightwatch
|
||||
```
|
||||
|
||||
@@ -34,8 +34,7 @@ module.exports = {
|
||||
## Installing in an Already Created Project
|
||||
|
||||
``` sh
|
||||
npm install -D @vue/cli-plugin-eslint
|
||||
vue invoke eslint
|
||||
vue add @vue/eslint
|
||||
```
|
||||
|
||||
## Injected webpack-chain Rules
|
||||
|
||||
@@ -80,8 +80,7 @@ module.exports = {
|
||||
## Installing in an Already Created Project
|
||||
|
||||
``` sh
|
||||
npm install -D @vue/cli-plugin-pwa
|
||||
vue invoke pwa
|
||||
vue add @vue/pwa
|
||||
```
|
||||
|
||||
## Injected webpack-chain Rules
|
||||
|
||||
@@ -25,8 +25,7 @@ If opted to use [TSLint](https://palantir.github.io/tslint/) during project crea
|
||||
## Installing in an Already Created Project
|
||||
|
||||
``` sh
|
||||
npm install -D @vue/cli-plugin-typescript
|
||||
vue invoke typescript
|
||||
vue add @vue/typescript
|
||||
```
|
||||
|
||||
## Injected webpack-chain Rules
|
||||
|
||||
@@ -44,7 +44,7 @@ test('classComponent', async () => {
|
||||
})
|
||||
|
||||
test('use with Babel', async () => {
|
||||
const { pkg, files } = await generateWithPlugin([
|
||||
const { files } = await generateWithPlugin([
|
||||
{
|
||||
id: 'babel',
|
||||
apply: require('@vue/cli-plugin-babel/generator'),
|
||||
@@ -59,7 +59,7 @@ test('use with Babel', async () => {
|
||||
}
|
||||
])
|
||||
|
||||
expect(pkg.babel).toEqual({ presets: ['@vue/app'] })
|
||||
expect(files['babel.config.js']).toMatch(`presets: [\n '@vue/app'\n ]`)
|
||||
expect(files['tsconfig.json']).toMatch(`"target": "esnext"`)
|
||||
})
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
jest.setTimeout(20000)
|
||||
jest.setTimeout(40000)
|
||||
|
||||
const create = require('@vue/cli-test-utils/createTestProject')
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
"jest": "^22.4.3",
|
||||
"jest-serializer-vue": "^1.0.0",
|
||||
"jest-transform-stub": "^1.0.0",
|
||||
"vue-jest": "^2.5.0"
|
||||
"vue-jest": "^2.6.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vue/test-utils": "^1.0.0-beta.16",
|
||||
|
||||
@@ -31,5 +31,5 @@
|
||||
## Installing in an Already Created Project
|
||||
|
||||
``` sh
|
||||
vue add unit-mocha
|
||||
vue add @vue/unit-mocha
|
||||
```
|
||||
|
||||
@@ -1,82 +1,3 @@
|
||||
let patched = false
|
||||
function patchWebpackChain () {
|
||||
if (patched) return
|
||||
|
||||
const Config = require('webpack-chain')
|
||||
|
||||
const toConfig = Config.prototype.toConfig
|
||||
Config.prototype.toConfig = function () {
|
||||
const config = toConfig.call(this)
|
||||
|
||||
// inject plugin metadata
|
||||
const { entries: plugins, order: pluginNames } = this.plugins.order()
|
||||
config.plugins.forEach((p, i) => {
|
||||
Object.defineProperties(p, {
|
||||
__pluginName: {
|
||||
value: pluginNames[i]
|
||||
},
|
||||
__pluginArgs: {
|
||||
value: plugins[pluginNames[i]].get('args')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
// inject rule metadata
|
||||
const { entries: rules, order: ruleNames } = this.module.rules.order()
|
||||
config.module.rules.forEach((rawRule, i) => {
|
||||
const ruleName = ruleNames[i]
|
||||
const rule = rules[ruleName]
|
||||
Object.defineProperties(rawRule, {
|
||||
__ruleName: {
|
||||
value: ruleName
|
||||
}
|
||||
})
|
||||
|
||||
if (rawRule.oneOf) {
|
||||
const { entries: oneOfs, order: oneOfNames } = rule.oneOfs.order()
|
||||
rawRule.oneOf.forEach((o, i) => {
|
||||
const oneOfName = oneOfNames[i]
|
||||
const oneOf = oneOfs[oneOfName]
|
||||
Object.defineProperties(o, {
|
||||
__ruleName: {
|
||||
value: ruleName
|
||||
},
|
||||
__oneOfName: {
|
||||
value: oneOfName
|
||||
}
|
||||
})
|
||||
patchUse(oneOf, ruleName, oneOfName, o)
|
||||
})
|
||||
}
|
||||
|
||||
patchUse(rule, ruleName, null, rawRule)
|
||||
})
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
patched = true
|
||||
}
|
||||
|
||||
function patchUse (rule, ruleName, oneOfName, rawRule) {
|
||||
if (Array.isArray(rawRule.use)) {
|
||||
const { order: useNames } = rule.uses.order()
|
||||
rawRule.use.forEach((use, i) => {
|
||||
Object.defineProperties(use, {
|
||||
__ruleName: {
|
||||
value: ruleName
|
||||
},
|
||||
__oneOfName: {
|
||||
value: oneOfName
|
||||
},
|
||||
__useName: {
|
||||
value: useNames[i]
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = (api, options) => {
|
||||
api.registerCommand('inspect', {
|
||||
description: 'inspect internal webpack config',
|
||||
@@ -90,20 +11,18 @@ module.exports = (api, options) => {
|
||||
'--verbose': 'show full function definitions in output'
|
||||
}
|
||||
}, args => {
|
||||
patchWebpackChain()
|
||||
|
||||
const get = require('get-value')
|
||||
const stringify = require('javascript-stringify')
|
||||
const { toString } = require('webpack-chain')
|
||||
const config = api.resolveWebpackConfig()
|
||||
const paths = args._
|
||||
const { _: paths, verbose } = args
|
||||
|
||||
let res
|
||||
if (args.rule) {
|
||||
res = config.module.rules.find(r => r.__ruleName === args.rule)
|
||||
res = config.module.rules.find(r => r.__ruleNames[0] === args.rule)
|
||||
} else if (args.plugin) {
|
||||
res = config.plugins.find(p => p.__pluginName === args.plugin)
|
||||
} else if (args.rules) {
|
||||
res = config.module.rules.map(r => r.__ruleName)
|
||||
res = config.module.rules.map(r => r.__ruleNames[0])
|
||||
} else if (args.plugins) {
|
||||
res = config.plugins.map(p => p.__pluginName)
|
||||
} else if (paths.length > 1) {
|
||||
@@ -117,54 +36,7 @@ module.exports = (api, options) => {
|
||||
res = config
|
||||
}
|
||||
|
||||
const pluginRE = /(?:function|class) (\w+Plugin)/
|
||||
const output = stringify(res, (value, indent, stringify) => {
|
||||
// shorten long functions
|
||||
if (
|
||||
!args.verbose &&
|
||||
typeof value === 'function' &&
|
||||
value.toString().length > 100
|
||||
) {
|
||||
return `function () { /* omitted long function */ }`
|
||||
}
|
||||
|
||||
// improve plugin output
|
||||
if (value && value.__pluginName) {
|
||||
let match = (
|
||||
value.constructor &&
|
||||
value.constructor.toString().match(pluginRE)
|
||||
)
|
||||
// copy-webpack-plugin
|
||||
if (value.__pluginName === 'copy') {
|
||||
match = [null, `CopyWebpackPlugin`]
|
||||
}
|
||||
const name = match[1]
|
||||
const prefix = `/* config.plugin('${value.__pluginName}') */\n`
|
||||
|
||||
if (name) {
|
||||
return prefix + `new ${name}(${
|
||||
value.__pluginArgs.map(arg => stringify(arg)).join(',\n')
|
||||
})`
|
||||
} else {
|
||||
return prefix + stringify({
|
||||
args: value.__pluginArgs || []
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// improve rule output
|
||||
if (value && value.__ruleName) {
|
||||
const prefix = `/* config.module.rule('${value.__ruleName}')${
|
||||
value.__oneOfName ? `.oneOf('${value.__oneOfName}')` : ``
|
||||
}${
|
||||
value.__useName ? `.use('${value.__useName}')` : ``
|
||||
} */\n`
|
||||
return prefix + stringify(value)
|
||||
}
|
||||
|
||||
return stringify(value)
|
||||
}, 2)
|
||||
|
||||
const output = toString(config, { verbose })
|
||||
console.log(output)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
module.exports = (api, options) => {
|
||||
api.chainWebpack(webpackConfig => {
|
||||
const resolveLocal = require('../util/resolveLocal')
|
||||
const getAssetPath = require('../util/getAssetPath')
|
||||
const inlineLimit = 10000
|
||||
|
||||
webpackConfig
|
||||
@@ -60,12 +61,12 @@ module.exports = (api, options) => {
|
||||
|
||||
webpackConfig.module
|
||||
.rule('images')
|
||||
.test(/\.(png|jpe?g|gif)(\?.*)?$/)
|
||||
.test(/\.(png|jpe?g|gif|webp)(\?.*)?$/)
|
||||
.use('url-loader')
|
||||
.loader('url-loader')
|
||||
.options({
|
||||
limit: inlineLimit,
|
||||
name: `img/[name].[hash:8].[ext]`
|
||||
name: getAssetPath(options, `img/[name].[hash:8].[ext]`)
|
||||
})
|
||||
|
||||
// do not base64-inline SVGs.
|
||||
@@ -76,7 +77,7 @@ module.exports = (api, options) => {
|
||||
.use('file-loader')
|
||||
.loader('file-loader')
|
||||
.options({
|
||||
name: `img/[name].[hash:8].[ext]`
|
||||
name: getAssetPath(options, `img/[name].[hash:8].[ext]`)
|
||||
})
|
||||
|
||||
webpackConfig.module
|
||||
@@ -86,7 +87,7 @@ module.exports = (api, options) => {
|
||||
.loader('url-loader')
|
||||
.options({
|
||||
limit: inlineLimit,
|
||||
name: `media/[name].[hash:8].[ext]`
|
||||
name: getAssetPath(options, `media/[name].[hash:8].[ext]`)
|
||||
})
|
||||
|
||||
webpackConfig.module
|
||||
@@ -96,7 +97,7 @@ module.exports = (api, options) => {
|
||||
.loader('url-loader')
|
||||
.options({
|
||||
limit: inlineLimit,
|
||||
name: `fonts/[name].[hash:8].[ext]`
|
||||
name: getAssetPath(options, `fonts/[name].[hash:8].[ext]`)
|
||||
})
|
||||
|
||||
// Other common pre-processors ---------------------------------------------
|
||||
|
||||
@@ -11,6 +11,8 @@ const findExisting = (context, files) => {
|
||||
|
||||
module.exports = (api, options) => {
|
||||
api.chainWebpack(webpackConfig => {
|
||||
const getAssetPath = require('../util/getAssetPath')
|
||||
|
||||
const {
|
||||
extract = true,
|
||||
sourceMap = false,
|
||||
@@ -22,8 +24,8 @@ module.exports = (api, options) => {
|
||||
const isProd = process.env.NODE_ENV === 'production'
|
||||
const shouldExtract = isProd && extract !== false && !shadowMode
|
||||
const extractOptions = Object.assign({
|
||||
filename: `css/[name].[contenthash:8].css`,
|
||||
chunkFilename: 'css/[name].[id].[contenthash:8].css'
|
||||
filename: getAssetPath(options, `css/[name].[contenthash:8].css`),
|
||||
chunkFilename: getAssetPath(options, 'css/[name].[id].[contenthash:8].css')
|
||||
}, extract && typeof extract === 'object' ? extract : {})
|
||||
|
||||
// check if the project has a valid postcss config
|
||||
@@ -103,6 +105,7 @@ module.exports = (api, options) => {
|
||||
}
|
||||
|
||||
createCSSRule('css', /\.css$/)
|
||||
createCSSRule('postcss', /\.p(ost)?css$/)
|
||||
createCSSRule('scss', /\.scss$/, 'sass-loader', loaderOptions.sass)
|
||||
createCSSRule('sass', /\.sass$/, 'sass-loader', Object.assign({
|
||||
indentedSyntax: true
|
||||
|
||||
@@ -21,7 +21,7 @@ module.exports = (api, options) => {
|
||||
.plugin('no-emit-on-errors')
|
||||
.use(require('webpack/lib/NoEmitOnErrorsPlugin'))
|
||||
|
||||
if (!process.env.VUE_CLI_TEST) {
|
||||
if (!process.env.VUE_CLI_TEST && options.devServer.progress !== false) {
|
||||
webpackConfig
|
||||
.plugin('progress')
|
||||
.use(require('webpack/lib/ProgressPlugin'))
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
module.exports = (api, options) => {
|
||||
api.chainWebpack(webpackConfig => {
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
const getAssetPath = require('../util/getAssetPath')
|
||||
|
||||
webpackConfig
|
||||
.mode('production')
|
||||
.devtool('source-map')
|
||||
.output
|
||||
.filename(`js/[name].[chunkhash:8].js`)
|
||||
.chunkFilename(`js/[name].[chunkhash:8].js`)
|
||||
.filename(getAssetPath(options, `js/[name].[chunkhash:8].js`))
|
||||
.chunkFilename(getAssetPath(options, `js/[name].[chunkhash:8].js`))
|
||||
|
||||
// keep module.id stable when vendor modules does not change
|
||||
webpackConfig
|
||||
|
||||
@@ -4,6 +4,7 @@ const schema = createSchema(joi => joi.object({
|
||||
baseUrl: joi.string(),
|
||||
devBaseUrl: joi.string(),
|
||||
outputDir: joi.string(),
|
||||
assetsDir: joi.string(),
|
||||
compiler: joi.boolean(),
|
||||
transpileDependencies: joi.array(),
|
||||
productionSourceMap: joi.boolean(),
|
||||
@@ -48,6 +49,9 @@ exports.defaults = () => ({
|
||||
// where to output built files
|
||||
outputDir: 'dist',
|
||||
|
||||
// where to put static assets (js/css/img/font/...)
|
||||
assetsDir: '',
|
||||
|
||||
// boolean, use full build?
|
||||
compiler: false,
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
const path = require('path')
|
||||
|
||||
module.exports = function getAssetPath (options, filePath) {
|
||||
return options.assetsDir
|
||||
? path.posix.join(options.assetsDir, filePath)
|
||||
: filePath
|
||||
}
|
||||
@@ -40,7 +40,6 @@
|
||||
"get-value": "^3.0.1",
|
||||
"globby": "^8.0.1",
|
||||
"html-webpack-plugin": "^3.2.0",
|
||||
"javascript-stringify": "^1.6.0",
|
||||
"launch-editor-middleware": "^2.2.1",
|
||||
"lodash.defaultsdeep": "^4.6.0",
|
||||
"lodash.mapvalues": "^4.6.0",
|
||||
@@ -60,10 +59,10 @@
|
||||
"thread-loader": "^1.1.5",
|
||||
"uglifyjs-webpack-plugin": "^1.2.5",
|
||||
"url-loader": "^1.0.1",
|
||||
"vue-loader": "^15.0.10",
|
||||
"vue-loader": "^15.0.11",
|
||||
"vue-template-compiler": "^2.5.16",
|
||||
"webpack": "^4.8.2",
|
||||
"webpack-chain": "^4.6.0",
|
||||
"webpack-chain": "^4.8.0",
|
||||
"webpack-dev-server": "^3.1.4",
|
||||
"webpack-merge": "^4.1.2",
|
||||
"yorkie": "^1.0.3"
|
||||
|
||||
@@ -463,10 +463,9 @@ test('extract config files', async () => {
|
||||
extractConfigFiles: true
|
||||
})
|
||||
|
||||
const json = v => JSON.stringify(v, null, 2)
|
||||
const js = v => `module.exports = ${stringifyJS(v, null, 2)}`
|
||||
expect(fs.readFileSync('/vue.config.js', 'utf-8')).toMatch(js(configs.vue))
|
||||
expect(fs.readFileSync('/.babelrc', 'utf-8')).toMatch(json(configs.babel))
|
||||
expect(fs.readFileSync('/babel.config.js', 'utf-8')).toMatch(js(configs.babel))
|
||||
expect(fs.readFileSync('/.postcssrc.js', 'utf-8')).toMatch(js(configs.postcss))
|
||||
expect(fs.readFileSync('/.eslintrc.js', 'utf-8')).toMatch(js(configs.eslintConfig))
|
||||
expect(fs.readFileSync('/jest.config.js', 'utf-8')).toMatch(js(configs.jest))
|
||||
|
||||
@@ -27,6 +27,7 @@ const {
|
||||
|
||||
const {
|
||||
log,
|
||||
warn,
|
||||
error,
|
||||
hasGit,
|
||||
hasYarn,
|
||||
@@ -169,6 +170,7 @@ module.exports = class Creator extends EventEmitter {
|
||||
}
|
||||
|
||||
// commit initial state
|
||||
let gitCommitFailed = false
|
||||
if (shouldInitGit) {
|
||||
await run('git add -A')
|
||||
if (isTestOrDebug) {
|
||||
@@ -176,7 +178,11 @@ module.exports = class Creator extends EventEmitter {
|
||||
await run('git', ['config', 'user.email', 'test@test.com'])
|
||||
}
|
||||
const msg = typeof cliOptions.git === 'string' ? cliOptions.git : 'init'
|
||||
await run('git', ['commit', '-m', msg])
|
||||
try {
|
||||
await run('git', ['commit', '-m', msg])
|
||||
} catch (e) {
|
||||
gitCommitFailed = true
|
||||
}
|
||||
}
|
||||
|
||||
// log instructions
|
||||
@@ -191,6 +197,13 @@ module.exports = class Creator extends EventEmitter {
|
||||
log()
|
||||
this.emit('creation', { event: 'done' })
|
||||
|
||||
if (gitCommitFailed) {
|
||||
warn(
|
||||
`Skipped git commit due to missing username and email in git config.\n` +
|
||||
`You will need to perform the initial commit yourself.\n`
|
||||
)
|
||||
}
|
||||
|
||||
generator.printExitLogs()
|
||||
}
|
||||
|
||||
|
||||
@@ -88,9 +88,15 @@ module.exports = class Generator {
|
||||
for (const key in this.pkg) {
|
||||
extract(key)
|
||||
}
|
||||
} else if (!process.env.VUE_CLI_TEST) {
|
||||
// by default, always extract vue.config.js
|
||||
extract('vue')
|
||||
} else {
|
||||
if (!process.env.VUE_CLI_TEST) {
|
||||
// by default, always extract vue.config.js
|
||||
extract('vue')
|
||||
}
|
||||
// always extract babel.config.js as this is the only way to apply
|
||||
// project-wide configuration even to dependencies.
|
||||
// TODO: this can be removed when Babel supports root: true in package.json
|
||||
extract('babel')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ function transformYAML (value, filename, source) {
|
||||
|
||||
module.exports = {
|
||||
vue: makeJSTransform('vue.config.js'),
|
||||
babel: makeJSONTransform('.babelrc'),
|
||||
babel: makeJSTransform('babel.config.js'),
|
||||
postcss: makeMutliExtensionJSONTransform('.postcssrc', true),
|
||||
eslintConfig: makeMutliExtensionJSONTransform('.eslintrc', true),
|
||||
jest: makeJSTransform('jest.config.js')
|
||||
|
||||
Reference in New Issue
Block a user