Skip to content

Commit 01edb46

Browse files
committed
feat: support config in dedicated files
1 parent 5288122 commit 01edb46

File tree

10 files changed

+135
-7
lines changed

10 files changed

+135
-7
lines changed

packages/@vue/cli-test-utils/assertPromptModule.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,13 @@ module.exports = async function assertPromptModule (
1818
}
1919
)
2020
expectedPrompts.push(
21+
{
22+
message: 'Where do you prefer placing config',
23+
choose: 1 // package.json
24+
},
2125
{
2226
message: 'package manager',
23-
choose: 0
27+
choose: 0 // yarn
2428
},
2529
{
2630
message: 'Save the preferences',
@@ -35,6 +39,7 @@ module.exports = async function assertPromptModule (
3539

3640
if (opts.plguinsOnly) {
3741
delete options.packageManager
42+
delete options.useConfigFiles
3843
}
3944
expect(options).toEqual(expectedOptions)
4045
}

packages/@vue/cli/__tests__/Creator.spec.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,11 @@ test('manual + PromptModuleAPI', async () => {
6767
choices: ['barChoice'],
6868
choose: 0
6969
},
70+
{
71+
message: 'Where do you prefer placing config',
72+
choices: ['dedicated', 'package.json'],
73+
choose: 0
74+
},
7075
{
7176
message: 'package manager',
7277
choices: ['Yarn', 'NPM'],
@@ -80,6 +85,7 @@ test('manual + PromptModuleAPI', async () => {
8085

8186
const expectedOptions = {
8287
packageManager: 'yarn',
88+
useConfigFiles: true,
8389
plugins: {
8490
bar: {},
8591
barChoice: {}

packages/@vue/cli/__tests__/Generator.spec.js

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ test('api: onCreateComplete', () => {
292292
api.onCreateComplete(fn)
293293
}
294294
}
295-
], cbs)
295+
], false, cbs)
296296
expect(cbs).toContain(fn)
297297
})
298298

@@ -306,3 +306,45 @@ test('api: resolve', () => {
306306
}
307307
])
308308
})
309+
310+
test('extract config files', async () => {
311+
const configs = {
312+
vue: {
313+
lintOnSave: true
314+
},
315+
babel: {
316+
presets: ['@vue/app']
317+
},
318+
postcss: {
319+
autoprefixer: {}
320+
},
321+
eslintConfig: {
322+
extends: ['plugin:vue/essential']
323+
},
324+
jest: {
325+
foo: 'bar'
326+
},
327+
browserslist: [
328+
'>=ie9'
329+
]
330+
}
331+
332+
const generator = new Generator('/', {}, [
333+
{
334+
id: 'test',
335+
apply: api => {
336+
api.extendPackage(configs)
337+
}
338+
}
339+
], true)
340+
341+
await generator.generate()
342+
343+
const json = v => JSON.stringify(v, null, 2)
344+
expect(fs.readFileSync('/vue.config.js', 'utf-8')).toMatch('module.exports = {\n lintOnSave: true\n}')
345+
expect(fs.readFileSync('/.babelrc', 'utf-8')).toMatch(json(configs.babel))
346+
expect(fs.readFileSync('/.postcssrc', 'utf-8')).toMatch(json(configs.postcss))
347+
expect(fs.readFileSync('/.eslintrc', 'utf-8')).toMatch(json(configs.eslintConfig))
348+
expect(fs.readFileSync('/.browserslistrc', 'utf-8')).toMatch(configs.browserslist.join('\n'))
349+
expect(fs.readFileSync('/jest.config.js', 'utf-8')).toMatch(`module.exports = {\n foo: 'bar'\n}`)
350+
})

packages/@vue/cli/lib/Creator.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ module.exports = class Creator {
138138
context,
139139
pkg,
140140
plugins,
141+
options.useConfigFiles,
141142
createCompleteCbs
142143
)
143144
await generator.generate()
@@ -193,6 +194,7 @@ module.exports = class Creator {
193194
// manual
194195
options = {
195196
packageManager: answers.packageManager || loadOptions().packageManager,
197+
useConfigFiles: answers.useConfigFiles === 'files',
196198
plugins: {}
197199
}
198200
// run cb registered by prompt modules to finalize the options
@@ -267,6 +269,24 @@ module.exports = class Creator {
267269
resolveOutroPrompts () {
268270
const outroPrompts = []
269271
const savedOptions = loadOptions()
272+
if (savedOptions.useConfigFiles == null) {
273+
outroPrompts.push({
274+
name: 'useConfigFiles',
275+
when: isMode('manual'),
276+
type: 'list',
277+
message: 'Where do you prefer placing config for Babel, PostCSS, ESLint, etc.?',
278+
choices: [
279+
{
280+
name: 'In dedicated config files',
281+
value: 'files'
282+
},
283+
{
284+
name: 'In package.json',
285+
value: 'pkg'
286+
}
287+
]
288+
})
289+
}
270290
if (hasYarn && !savedOptions.packageManager) {
271291
outroPrompts.push({
272292
name: 'packageManager',

packages/@vue/cli/lib/Generator.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
const ejs = require('ejs')
22
const slash = require('slash')
33
const debug = require('debug')
4+
const configMap = require('./util/configMap')
45
const GeneratorAPI = require('./GeneratorAPI')
56
const sortObject = require('./util/sortObject')
67
const writeFileTree = require('./util/writeFileTree')
78

89
module.exports = class Generator {
9-
constructor (context, pkg, plugins, completeCbs = []) {
10+
constructor (context, pkg, plugins, extractConfigFiles, completeCbs = []) {
1011
this.context = context
1112
this.plugins = plugins
1213
this.pkg = pkg
@@ -26,6 +27,11 @@ module.exports = class Generator {
2627
const api = new GeneratorAPI(id, this, options, rootOptions || {})
2728
apply(api, options, rootOptions)
2829
})
30+
// if the user has chosen so, extract configs from package.json into
31+
// dedicated files.
32+
if (extractConfigFiles) {
33+
this.extractConfigFiles()
34+
}
2935
}
3036

3137
async generate () {
@@ -38,6 +44,17 @@ module.exports = class Generator {
3844
await writeFileTree(this.context, this.files)
3945
}
4046

47+
extractConfigFiles () {
48+
for (const key in this.pkg) {
49+
if (configMap[key]) {
50+
const value = this.pkg[key]
51+
const { transform, filename } = configMap[key]
52+
this.files[filename] = transform(value)
53+
delete this.pkg[key]
54+
}
55+
}
56+
}
57+
4158
sortPkg () {
4259
// ensure package.json keys has readable order
4360
this.pkg.dependencies = sortObject(this.pkg.dependencies)

packages/@vue/cli/lib/invoke.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ async function invoke (pluginName, options) {
1919
delete options._
2020
const context = process.cwd()
2121
const pkgPath = path.resolve(context, 'package.json')
22+
const isTestOrDebug = process.env.VUE_CLI_TEST || process.env.VUE_CLI_DEBUG
2223

2324
if (!fs.existsSync(pkgPath)) {
2425
error(`package.json not found in ${chalk.yellow(context)}`)
@@ -60,14 +61,14 @@ async function invoke (pluginName, options) {
6061
context,
6162
pkg,
6263
[plugin],
64+
isTestOrDebug ? false : loadOptions().useConfigFiles,
6365
createCompleteCbs
6466
)
6567

6668
log()
6769
logWithSpinner('🚀', `Invoking generator for ${id}...`)
6870
await generator.generate()
6971

70-
const isTestOrDebug = process.env.VUE_CLI_TEST || process.env.VUE_CLI_DEBUG
7172
const newDeps = generator.pkg.dependencies
7273
const newDevDeps = generator.pkg.devDependencies
7374
const depsChanged = (

packages/@vue/cli/lib/options.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ const schema = createSchema(joi => joi.object().keys({
1919
cssPreprocessor: joi.string().only(['sass', 'less', 'stylus']),
2020
useTaobaoRegistry: joi.boolean(),
2121
packageManager: joi.string().only(['yarn', 'npm']),
22+
useConfigFiles: joi.boolean(),
2223
plugins: joi.object().required()
2324
}))
2425

@@ -28,6 +29,7 @@ exports.defaults = {
2829
router: false,
2930
vuex: false,
3031
cssPreprocessor: undefined,
32+
useConfigFiles: undefined,
3133
useTaobaoRegistry: undefined,
3234
packageManager: hasYarn ? 'yarn' : 'npm',
3335
plugins: {
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
const stringifyJS = require('javascript-stringify')
2+
const json = value => JSON.stringify(value, null, 2)
3+
const js = value => `module.exports = ${stringifyJS(value, null, 2)}`
4+
5+
module.exports = {
6+
vue: {
7+
filename: 'vue.config.js',
8+
transform: js
9+
},
10+
babel: {
11+
filename: '.babelrc',
12+
transform: json
13+
},
14+
postcss: {
15+
filename: '.postcssrc',
16+
transform: json
17+
},
18+
eslintConfig: {
19+
filename: '.eslintrc',
20+
transform: json
21+
},
22+
jest: {
23+
filename: 'jest.config.js',
24+
transform: js
25+
},
26+
browserslist: {
27+
filename: '.browserslistrc',
28+
transform: value => value.join('\n')
29+
}
30+
// 'lint-staged': {
31+
// filename: '.lintstagedrc',
32+
// transform: json
33+
// }
34+
}

packages/@vue/cli/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
"import-global": "^0.1.0",
3838
"inquirer": "^4.0.1",
3939
"isbinaryfile": "^3.0.2",
40+
"javascript-stringify": "^1.6.0",
4041
"klaw-sync": "^3.0.2",
4142
"lodash.clonedeep": "^4.5.0",
4243
"minimist": "^1.2.0",

yarn.lock

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6857,9 +6857,9 @@ mocha-webpack@^1.0.1:
68576857
toposort "^1.0.0"
68586858
yargs "^4.8.0"
68596859

6860-
mocha@^5.0.0:
6861-
version "5.0.0"
6862-
resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.0.0.tgz#cccac988b0bc5477119cba0e43de7af6d6ad8f4e"
6860+
mocha@^4.1.0:
6861+
version "4.1.0"
6862+
resolved "https://registry.yarnpkg.com/mocha/-/mocha-4.1.0.tgz#7d86cfbcf35cb829e2754c32e17355ec05338794"
68636863
dependencies:
68646864
browser-stdout "1.3.0"
68656865
commander "2.11.0"

0 commit comments

Comments
 (0)