Skip to content

Commit c6b1f5f

Browse files
author
Baitu Huang
committed
feat: support watch set extra file list
1 parent 4d13ad6 commit c6b1f5f

File tree

5 files changed

+66
-37
lines changed

5 files changed

+66
-37
lines changed

README.md

+15-7
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ npm install vue-flags-webpack-plugin -D
1515
options:
1616
* `flags` ({[k: string]: boolean} | string, required)
1717

18-
a plain object that contains flags value(boolean) or a file path that exports flags object.
18+
a plain object that contains flags value(boolean) or a file path that exports the final flags object.
1919
```javascript
2020
flags: {
2121
FLAG_A: true,
@@ -27,24 +27,32 @@ options:
2727
* `namespace` (string, required)
2828

2929
used as namespace of flags in JavaScript, must be a valid variable name.
30-
* `watch` (boolean, default: false)
30+
* `watch` (boolean | string[], default: false)
3131

32-
Support to modify flags and reload your app when this option is `true`.
32+
Support to modify flags and reload your app when this option is set.
3333

34-
Set `true` ONLY in development mode, eg: `watch: process.env.NODE_ENV === 'development'`.
34+
Set this option ONLY in development mode.
35+
36+
If `watch` is `true`, option `flags` must be a file path.
37+
38+
`watch` could also be an array including extra files paths which will be watched.
39+
```javascript
40+
watch: process.env.NODE_ENV === 'development'
41+
// or
42+
watch: [ './config/flag1.js', './config/flag2.js' ]
43+
```
3544

36-
Note that `flags` must be a file path when this options is `true`.
3745
* `ignoreFiles` ({[k: string]: RegExp | RegExp[]})
3846

3947
A plain object that uses flag name or expression as key and regexp as value.
4048

4149
Modules(absolute path) matched by the regexps will be ignored when the value of flags is `false`.
4250
```javascript
43-
{
51+
ignoreFiles: {
4452
// if FLAG_A is false, a.js will be ignored,
4553
'FLAG_A': [/a\.js$/],
4654
// if FLAG_A is false or FLAG_B is true, a-b.js will be ignored
47-
'FLAG_A && !FLAG_B': [/a-b\.js$/],
55+
'FLAG_A && !FLAG_B': [/a-not-b\.js$/],
4856
}
4957
```
5058

lib/plugin.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ module.exports = class VueFlagsWebpackPlugin {
7676
// prepend ignore module pitch loader
7777
if (this.pluginOptions.ignoreFiles) {
7878
const { allFiles } = this.pluginOptions
79-
rules.unshift({
79+
allFiles.length && rules.unshift({
8080
use: [{
8181
loader: require.resolve('./ignore-module-loader'),
8282
enforce: 'post', // call pitch as soon

lib/resolve-options.js

+24-7
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ const clearModule = require('clear-module')
55
const validateOptions = require('schema-utils')
66

77
const { RESOLVED_FLAGS_PATH, PLUGIN_NAME } = require('./constants')
8-
const { genError, toFunc, getDependencies } = require('./utils')
8+
const { genError, toFunc } = require('./utils')
99

1010
const flagsSchema = {
1111
type: 'object',
@@ -39,7 +39,6 @@ const optionSchema = watch => {
3939
{ instanceof: 'RegExp' },
4040
{
4141
type: 'array',
42-
minItems: 1,
4342
items: { instanceof: 'RegExp' }
4443
}
4544
]
@@ -48,7 +47,15 @@ const optionSchema = watch => {
4847
additionalProperties: true
4948
},
5049
namespace: { type: 'string', minLength: 1 },
51-
watch: { type: 'boolean' }
50+
watch: {
51+
oneOf: [
52+
{ type: 'boolean' },
53+
{
54+
type: 'array',
55+
items: { type: 'string', minLength: 1 }
56+
}
57+
]
58+
}
5259
}
5360
}
5461
}
@@ -85,6 +92,8 @@ function updateGetFlags (flagsPaths, errors = 0) {
8592
if (Array.isArray(flagsPaths)) {
8693
flagsPaths.forEach(fp => clearModule(fp))
8794
flagPath = flagsPaths[0]
95+
} else {
96+
clearModule(flagPath)
8897
}
8998
let newFlags
9099
try {
@@ -129,17 +138,25 @@ function setOptions ({ flags, ignoreFiles, namespace, watch }, context, watchOpt
129138
if (!dev) {
130139
throw genError('Make sure only use "watch" in development mode!')
131140
}
132-
const flagFiles = getDependencies(() => {
133-
pluginOptions.flags = updateGetFlags(flags)
134-
}, [flags])
141+
pluginOptions.flags = updateGetFlags(flags)
142+
const flagFiles = [flags]
143+
if (Array.isArray(watch)) {
144+
watch.forEach(file => {
145+
if (!path.isAbsolute(file)) {
146+
flagFiles.push(path.resolve(context, file))
147+
} else {
148+
flagFiles.push(file)
149+
}
150+
})
151+
}
135152
const watcher = new Watchpack(Object.assign({}, watchOptions))
136153
watcher.watch(flagFiles, [], Date.now() - 100)
137154
let delay // some file systems will trigger "change" event many times
138155
watcher.on('change', () => {
139156
clearTimeout(delay)
140157
delay = setTimeout(() => {
141158
pluginOptions.flags = updateGetFlags(flagFiles)
142-
}, 300)
159+
}, 338) // 🙂
143160
})
144161
// in order to be able to close it
145162
pluginOptions.watcher = watcher

lib/utils.js

-20
Original file line numberDiff line numberDiff line change
@@ -34,23 +34,3 @@ exports.toFunc = function toFunc (exp, useWith = true) {
3434
}
3535
return funcsMap[exp]
3636
}
37-
38-
const Module = require('module')
39-
const path = require('path')
40-
exports.getDependencies = function getDependencies (callback, init) {
41-
const deps = new Set(init)
42-
const resolveFilename = Module._resolveFilename
43-
Module._resolveFilename = function _resolveFilename (req, ...args) {
44-
const filename = resolveFilename.call(this, req, ...args)
45-
if (path.isAbsolute(req) && !/node_modules/.test(req)) {
46-
deps.add(filename)
47-
}
48-
if (/^\.{1,2}\//.test(req)) {
49-
deps.add(filename)
50-
}
51-
return filename
52-
}
53-
callback()
54-
Module._resolveFilename = resolveFilename
55-
return [...deps]
56-
}

test/options.test.js

+26-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
const test = require('tape')
22
const chalk = require('chalk')
33
process.env.NODE_ENV = 'TEST'
4+
45
const { setOptions, validateOptions } = require('../lib/resolve-options')
56

67
test(chalk.cyan('options test:valid'), t => {
@@ -18,6 +19,16 @@ test(chalk.cyan('options test:valid'), t => {
1819
flags: { foo: true },
1920
ignoreFiles: { foo: /a/ }
2021
},
22+
{
23+
namespace: 'N',
24+
flags: { foo: true },
25+
ignoreFiles: { foo: [/a/] }
26+
},
27+
{
28+
namespace: 'N',
29+
flags: { foo: true },
30+
ignoreFiles: { foo: [] }
31+
},
2132
{
2233
namespace: 'N',
2334
flags: {},
@@ -26,15 +37,28 @@ test(chalk.cyan('options test:valid'), t => {
2637
{
2738
namespace: 'N',
2839
flags: './test/flags.js',
29-
watch: false
40+
watch: true
3041
},
3142
{
3243
namespace: 'N',
3344
flags: './test/flags.js'
45+
},
46+
{
47+
namespace: 'N',
48+
flags: './test/flags.js',
49+
watch: []
50+
},
51+
{
52+
namespace: 'N',
53+
flags: './test/flags.js',
54+
watch: [ './foo.js' ]
3455
}
3556
].forEach(option => {
3657
t.equal(validateOptions(option), option)
37-
t.equal(setOptions(option, './', {}, true).namespace, option.namespace)
58+
const po = setOptions(option, './', {}, true)
59+
t.equal(po.namespace, option.namespace)
60+
t.equal(!!option.watch, !!po.watcher)
61+
po.watcher && po.watcher.close()
3862
})
3963
t.end()
4064
})

0 commit comments

Comments
 (0)