Skip to content

Commit ead5716

Browse files
committed
Revert to old API and extend native arrays and objects
1 parent 7cd8a0f commit ead5716

File tree

13 files changed

+253
-174
lines changed

13 files changed

+253
-174
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
const environment = require('./environment')
22

3-
module.exports = environment.config
3+
module.exports = environment.toWebpackConfig()
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
const environment = require('./environment')
22

3-
module.exports = environment.config
3+
module.exports = environment.toWebpackConfig()

lib/install/config/webpack/test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
const environment = require('./environment')
22

3-
module.exports = environment.config
3+
module.exports = environment.toWebpackConfig()

package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,7 @@
3535
"sass-loader": "^6.0.6",
3636
"style-loader": "^0.18.2",
3737
"webpack": "^3.5.5",
38-
"webpack-manifest-plugin": "^1.3.1",
39-
"webpack-merge": "^4.1.0"
38+
"webpack-manifest-plugin": "^1.3.1"
4039
},
4140
"devDependencies": {
4241
"eslint": "^3.16.1",

package/config-types/config-list.js

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/**
2+
* @class
3+
* @extends { Array }
4+
*/
5+
6+
class ConfigList extends Array {
7+
set(key, value, pos = 'bottom') {
8+
const index = this.index(key)
9+
if (index >= 0) this.delete(key)
10+
return this.add({ key, value }, pos)
11+
}
12+
13+
get(key) {
14+
if (this.index(key) < 0) throw new Error(`Item ${key} not found in the list`)
15+
return this[this.index(key)].value
16+
}
17+
18+
insertAtPos(index, item) {
19+
return this.splice(index, 0, item)
20+
}
21+
22+
delete(key) {
23+
const index = this.index(key)
24+
if (index) return this.splice(index, 1)
25+
return this
26+
}
27+
28+
index(key) {
29+
return this.findIndex(entry =>
30+
(
31+
entry === key ||
32+
entry.key === key ||
33+
(entry.constructor && entry.constructor.name === key)
34+
)
35+
)
36+
}
37+
38+
values() {
39+
return this.map(item => item.value)
40+
}
41+
42+
keys() {
43+
return this.map(item => item.key)
44+
}
45+
46+
add(item, pos) {
47+
if (pos === 'top') {
48+
this.unshift(item)
49+
} else if (typeof pos === 'number') {
50+
this.insertAtPos(pos, item)
51+
} else {
52+
this.push(item)
53+
}
54+
return this
55+
}
56+
}
57+
58+
module.exports = ConfigList

package/config-types/config-object.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
const deepMerge = require('./utils')
2+
3+
/**
4+
* @class
5+
* @extends { Object }
6+
*/
7+
8+
class ConfigObject extends Object {
9+
get(key) {
10+
return this[key]
11+
}
12+
13+
set(key, value) {
14+
this[key] = value
15+
return this
16+
}
17+
18+
delete(key) {
19+
if (!this[key]) throw new Error(`Config prop ${key} not found`)
20+
delete this[key]
21+
return this
22+
}
23+
24+
toObject() {
25+
const object = {}
26+
Object.keys(this).forEach(key => (object[key] = this[key]))
27+
return object
28+
}
29+
30+
merge(config) {
31+
return Object.assign(this, deepMerge(this, config))
32+
}
33+
}
34+
35+
module.exports = ConfigObject

package/config-types/index.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
const ConfigObject = require('./config-object')
2+
const ConfigList = require('./config-list')
3+
4+
module.exports = {
5+
ConfigObject,
6+
ConfigList
7+
}

package/config-types/utils.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
const isObject = value => (
2+
typeof value === 'object' &&
3+
value !== null &&
4+
(value.length === undefined || value.length === null)
5+
)
6+
7+
const isArray = value => Array.isArray(value)
8+
9+
const isEqual = (target, source) => JSON.stringify(target) === JSON.stringify(source)
10+
11+
const deepMerge = (target, source) => {
12+
if (!target) return source
13+
if (!source) return target
14+
if (isEqual(target, source)) return source
15+
if (isArray(target) && isArray(source)) return [...new Set([...target, ...source])]
16+
if (!(isObject(target) && isObject(source))) return source
17+
18+
return [...Object.keys(target), ...Object.keys(source)].reduce(
19+
(result, key) =>
20+
(Object.assign(
21+
{},
22+
result,
23+
{ [key]: deepMerge(target[key], source[key]) }
24+
)),
25+
{}
26+
)
27+
}
28+
29+
module.exports = deepMerge

package/environment.js

Lines changed: 60 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -6,133 +6,99 @@ const { sync } = require('glob')
66
const extname = require('path-complete-extname')
77

88
const webpack = require('webpack')
9-
const merge = require('webpack-merge')
109
const ExtractTextPlugin = require('extract-text-webpack-plugin')
1110
const ManifestPlugin = require('webpack-manifest-plugin')
1211

12+
const { ConfigList, ConfigObject } = require('./config-types')
1313
const rules = require('./rules')
14+
const config = require('./config')
1415
const assetHost = require('./asset_host')
15-
const {
16-
source_path: sourcePath,
17-
resolved_paths: resolvedPaths,
18-
source_entry_path: sourceEntryPath,
19-
extensions
20-
} = require('./config')
21-
22-
const getBaseLoaders = () =>
23-
Object.values(rules).map(rule => rule)
24-
25-
const getBaseResolvedModules = () => {
26-
const result = []
27-
result.push(resolve(sourcePath))
28-
result.push('node_modules')
29-
if (resolvedPaths) {
30-
resolvedPaths.forEach(path => result.push(path))
31-
}
16+
17+
const getLoaderList = () => {
18+
const result = new ConfigList()
19+
Object.entries(rules).forEach(([key, rule]) => result.set(key, rule))
20+
return result
21+
}
22+
23+
const getPluginList = () => {
24+
const result = new ConfigList()
25+
result.set('Environment', new webpack.EnvironmentPlugin(JSON.parse(JSON.stringify(process.env))))
26+
result.set('ExtractText', new ExtractTextPlugin('[name]-[contenthash].css'))
27+
result.set('Manifest', new ManifestPlugin({ publicPath: assetHost.publicPath, writeToFileEmit: true }))
3228
return result
3329
}
3430

3531
const getExtensionsGlob = () => {
32+
const { extensions } = config
3633
if (!extensions.length) {
3734
throw new Error('You must configure at least one extension to compile in webpacker.yml')
3835
}
3936
return extensions.length === 1 ? `**/${extensions[0]}` : `**/*{${extensions.join(',')}}`
4037
}
4138

4239
const getEntryObject = () => {
43-
const result = {}
40+
const result = new ConfigObject()
4441
const glob = getExtensionsGlob()
45-
const entryPath = join(sourcePath, sourceEntryPath)
46-
const entryPaths = sync(join(entryPath, glob))
47-
entryPaths.forEach((path) => {
48-
const namespace = relative(join(entryPath), dirname(path))
42+
const rootPath = join(config.source_path, config.source_entry_path)
43+
const paths = sync(join(rootPath, glob))
44+
paths.forEach((path) => {
45+
const namespace = relative(join(rootPath), dirname(path))
4946
const name = join(namespace, basename(path, extname(path)))
50-
result[name] = resolve(path)
47+
result.set(name, resolve(path))
5148
})
5249
return result
5350
}
5451

55-
const makeArray = obj => (Array.isArray(obj) ? obj : [obj])
52+
const getModulePaths = () => {
53+
let result = new ConfigList()
54+
result.set('source', resolve(config.source_path))
55+
result.set('node_modules', 'node_modules')
56+
if (config.resolved_paths) {
57+
result = result.concat(config.resolved_paths)
58+
}
59+
return result
60+
}
5661

57-
module.exports = class Environment {
58-
constructor() {
59-
this.mergeOptions = {
60-
entry: 'append',
61-
'module.rules': 'append',
62-
plugins: 'append'
62+
const getBaseConfig = () =>
63+
new ConfigObject().merge({
64+
output: {
65+
filename: '[name]-[chunkhash].js',
66+
chunkFilename: '[name]-[chunkhash].chunk.js',
67+
path: assetHost.path,
68+
publicPath: assetHost.publicPath
69+
},
70+
71+
resolve: {
72+
extensions: config.extensions
73+
},
74+
75+
resolveLoader: {
76+
modules: ['node_modules']
6377
}
78+
})
6479

65-
this.config = {
66-
entry: getEntryObject(),
67-
68-
output: {
69-
filename: '[name]-[chunkhash].js',
70-
chunkFilename: '[name]-[chunkhash].chunk.js',
71-
path: assetHost.path,
72-
publicPath: assetHost.publicPath
73-
},
74-
75-
module: {
76-
rules: getBaseLoaders()
77-
},
78-
79-
plugins: [
80-
new webpack.EnvironmentPlugin(JSON.parse(JSON.stringify(process.env))),
81-
new ExtractTextPlugin('[name]-[contenthash].css'),
82-
new ManifestPlugin({ publicPath: assetHost.publicPath, writeToFileEmit: true })
83-
],
84-
85-
resolve: {
86-
extensions,
87-
modules: getBaseResolvedModules()
88-
},
89-
90-
resolveLoader: {
91-
modules: ['node_modules']
92-
}
93-
}
80+
module.exports = class Environment {
81+
constructor() {
82+
this.loaders = getLoaderList()
83+
this.plugins = getPluginList()
84+
this.config = getBaseConfig()
85+
this.entry = getEntryObject()
86+
this.resolvedModules = getModulePaths()
9487
}
9588

96-
addEntry(entry) {
97-
this.mergeConfig({
98-
entry: makeArray(entry)
99-
})
100-
}
89+
toWebpackConfig() {
90+
return this.config.merge({
91+
entry: this.entry.toObject(),
10192

102-
addRule(rule) {
103-
this.mergeConfig({
10493
module: {
105-
rules: makeArray(rule)
106-
}
107-
})
108-
}
94+
rules: this.loaders.values()
95+
},
10996

110-
addPlugin(plugin) {
111-
this.mergeConfig({
112-
plugins: makeArray(plugin)
113-
})
114-
}
97+
plugins: this.plugins.values(),
11598

116-
addResolvedModule(module) {
117-
this.mergeConfig({
11899
resolve: {
119-
modules: makeArray(module)
100+
modules: this.resolvedModules.values()
120101
}
121102
})
122103
}
123-
124-
addLoader(ruleName, loader) {
125-
makeArray(ruleName).forEach(rule => this.updateRule(rule, { use: makeArray(loader) }))
126-
}
127-
128-
updateRule(name, options = {}) {
129-
const rule = rules[name]
130-
if (!rule) throw new Error(`Rule ${name} not found in ${JSON.stringify(rules, null, 2)}`)
131-
this.addRule(merge.smart(rule, options))
132-
}
133-
134-
mergeConfig(config) {
135-
this.config = merge.smartStrategy(this.mergeOptions)(this.config, config)
136-
return this.config
137-
}
138104
}

0 commit comments

Comments
 (0)