Skip to content

Commit aeee006

Browse files
committed
feat: add subModule
1 parent 8c2ff84 commit aeee006

12 files changed

Lines changed: 1178 additions & 868 deletions

File tree

package.json

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -48,35 +48,36 @@
4848
}
4949
},
5050
"peerDependencies": {
51-
"@micro-app/core": "^0.3.18"
51+
"@micro-app/core": "^0.3.27",
52+
"@micro-app/cli": "^0.3.16"
5253
},
5354
"devDependencies": {
54-
"@babel/core": "^7.9.0",
55-
"@babel/preset-env": "^7.9.5",
5655
"@micro-app/cli": "^0.3.15",
57-
"@micro-app/plugin-compatible": "0.0.3",
56+
"@micro-app/plugin-compatible": "0.0.4",
5857
"@micro-app/plugin-deploy": "^0.0.7",
5958
"@types/jest": "^24.9.1",
6059
"eslint-config-2o3t": "^2.0.1",
61-
"html-webpack-plugin": "^3.2.0",
60+
"html-webpack-plugin": "^4.2.0",
6261
"husky": "^3.1.0",
6362
"jest": "^24.9.0",
6463
"typescript": "^3.8.3",
6564
"vue": "^2.6.11"
6665
},
6766
"dependencies": {
67+
"@babel/core": "^7.9.0",
68+
"@babel/preset-env": "^7.9.5",
6869
"@intervolga/optimize-cssnano-plugin": "^1.0.6",
6970
"@marshallofsound/webpack-asset-relocator-loader": "^0.5.0",
70-
"@micro-app/shared-utils": "^0.1.17",
71+
"@micro-app/shared-utils": "^0.1.18",
7172
"@soda/friendly-errors-webpack-plugin": "^1.7.1",
7273
"address": "^1.1.2",
73-
"autoprefixer": "^9.7.4",
74+
"autoprefixer": "^9.7.6",
7475
"babel-loader": "^8.1.0",
7576
"cache-loader": "^4.1.0",
7677
"case-sensitive-paths-webpack-plugin": "^2.3.0",
7778
"cli-highlight": "^2.1.4",
7879
"clipboardy": "^2.3.0",
79-
"css-loader": "^3.4.2",
80+
"css-loader": "^3.5.2",
8081
"cssnano": "^4.1.10",
8182
"default-gateway": "^6.0.0",
8283
"file-loader": "^5.1.0",
@@ -86,12 +87,13 @@
8687
"portfinder": "^1.0.25",
8788
"postcss-loader": "^3.0.0",
8889
"ts-loader": "^6.2.2",
89-
"url-loader": "^4.0.0",
90+
"url-loader": "^4.1.0",
9091
"vue-loader": "^15.9.1",
9192
"vue-style-loader": "^4.1.2",
9293
"webpack": "^4",
9394
"webpack-chain": "^6.4.0",
94-
"webpack-dev-server": "^3"
95+
"webpack-dev-server": "^3",
96+
"webpack-manifest-plugin": "^2.2.0"
9597
},
9698
"peerDependenciesMeta": {
9799
"less-loader": {

src/config/index.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
'use strict';
2+
3+
const SKIP_CONTEXT = [ '--pure-webpack-unified-config' ]; // context
4+
const DEPENDENCIES_PLUGIN = [ '@micro-app/cli' ]; // dependencies
5+
6+
module.exports = {
7+
SKIP_CONTEXT,
8+
DEPENDENCIES_PLUGIN,
9+
};
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
'use strict';
2+
3+
const { hash, tryRequire, path } = require('@micro-app/shared-utils');
4+
5+
const SUB_MODULES_FILE_NAME = 'subsidiary';
6+
7+
module.exports = function configParser(selfConfig = {}) {
8+
const originalConfig = selfConfig.originalConfig || {};
9+
const subModule = originalConfig.subModule || {};
10+
11+
function entry() {
12+
const entry = subModule.entry || {};
13+
// fix entry path
14+
if (typeof entry === 'object') {
15+
Object.keys(entry).forEach(key => {
16+
const _entrys = entry[key];
17+
if (Array.isArray(_entrys)) {
18+
entry[getNewKey(key)] = _entrys.map(item => {
19+
if (!tryRequire.resolve(item)) {
20+
return path.resolve(selfConfig.root, item);
21+
}
22+
return item;
23+
});
24+
} else if (typeof _entrys === 'string') {
25+
if (!tryRequire.resolve(_entrys)) {
26+
entry[getNewKey(key)] = [ path.resolve(selfConfig.root, _entrys) ];
27+
}
28+
}
29+
});
30+
} else if (Array.isArray(entry)) {
31+
return {
32+
[getNewKey('index')]: entry.map(item => {
33+
if (!tryRequire.resolve(item)) {
34+
return path.resolve(selfConfig.root, item);
35+
}
36+
return item;
37+
}),
38+
};
39+
} else if (typeof entry === 'string') {
40+
return {
41+
[getNewKey('index')]: [ path.resolve(selfConfig.root, entry) ],
42+
};
43+
}
44+
return entry;
45+
}
46+
47+
function prefix() {
48+
const _prefix = subModule.prefix || SUB_MODULES_FILE_NAME;
49+
return `${_prefix}-`;
50+
}
51+
52+
function namespace() {
53+
const key = hash(selfConfig.key);
54+
const _namespace = subModule.namespace || key;
55+
return _namespace;
56+
}
57+
58+
function fileName() {
59+
return `manifest/${namespace()}.json`;
60+
}
61+
62+
function getNewKey(key) {
63+
return `${prefix()}_${namespace()}-${key}`;
64+
}
65+
66+
return {
67+
entry,
68+
namespace,
69+
prefix,
70+
fileName,
71+
};
72+
};
73+
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
'use strict';
2+
3+
module.exports = {
4+
additionalProperties: true,
5+
properties: {
6+
subModule: {
7+
description: '子模块配置. ( object )',
8+
type: 'object',
9+
additionalProperties: true,
10+
properties: {
11+
entry: {
12+
description: '入口配置. ( object )',
13+
type: 'object',
14+
},
15+
publicPath: {
16+
description: 'public resource path. ( stirng )',
17+
type: 'string',
18+
},
19+
outputDir: {
20+
description: 'output resource path. ( stirng )',
21+
type: 'string',
22+
},
23+
},
24+
required: [ 'entry' ],
25+
},
26+
},
27+
type: 'object',
28+
};

src/extends/submodule/index.js

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
'use strict';
2+
3+
module.exports = function subModuleWebpack(api, opts) {
4+
5+
api.assertVersion('>=0.3.26');
6+
7+
const registerMethods = require('./methods');
8+
registerMethods(api);
9+
10+
// TODO 只有开启 --sub-module 时才处理
11+
if (!api.context.subModule) {
12+
return;
13+
}
14+
15+
// 解析 subModule 参数,只查询自己模块的
16+
const selfConfig = api.selfConfig || {};
17+
const originalConfig = selfConfig.originalConfig || {};
18+
19+
const subModule = originalConfig.subModule;
20+
if (!subModule) {
21+
return;
22+
}
23+
24+
// 增加校验配置
25+
api.validateSchema(require('./configSchema'), originalConfig);
26+
27+
const configParser = require('./configParser');
28+
const _configParser = configParser(selfConfig);
29+
30+
// 直接在 config 上设置, 扩增 config 配置
31+
const config = api.config;
32+
config.subModule = config.subModule || {};
33+
34+
Object.assign(config.subModule, subModule, {
35+
prefix: _configParser.prefix(),
36+
namespace: _configParser.namespace(),
37+
entry: _configParser.entry(),
38+
fileName: _configParser.fileName(),
39+
});
40+
41+
// change config.pages
42+
const entryPoints = config.subModule.entry;
43+
config.pages = {
44+
...Object.keys(entryPoints).reduce((obj, key) => {
45+
obj[key] = {
46+
entry: entryPoints[key],
47+
};
48+
return obj;
49+
}, {}),
50+
};
51+
52+
// externals, 注入全局 window
53+
54+
55+
// 生成 manifest
56+
api.modifyChainWebpackConfig(webpackChain => {
57+
const otherOptions = Object.keys(config.subModule).reduce((obj, key) => {
58+
if (![ 'prefix', 'namespace', 'entry' ].includes(key)) {
59+
obj[key] = config.subModule[key];
60+
}
61+
return obj;
62+
}, {});
63+
64+
const ManifestPlugin = require('webpack-manifest-plugin');
65+
webpackChain.plugin('assets-manifest')
66+
.use(ManifestPlugin, [{
67+
generate(seed, files, entrypoints) {
68+
return files.reduce((manifest, descriptor) => {
69+
const { name, path, isInitial, isChunk } = descriptor;
70+
if (descriptor.name.toLowerCase().endsWith('.map')) {
71+
manifest.map = { ...(manifest.map || {}), [name]: path };
72+
} else if (isInitial) {
73+
manifest.entry = { ...(manifest.entry || {}), [name]: path };
74+
} else if (isChunk) {
75+
manifest.assets = { ...(manifest.assets || {}), [name]: path };
76+
} else {
77+
manifest.static = { ...(manifest.static || {}), [name]: path };
78+
}
79+
return manifest;
80+
}, seed);
81+
},
82+
...otherOptions,
83+
}])
84+
.end();
85+
86+
return webpackChain;
87+
});
88+
89+
api.modifyWebpackConfig(webpackConfig => {
90+
const namespace = config.subModule.namespace;
91+
const prefix = config.subModule.prefix;
92+
93+
// chunkFilename
94+
const chunkFilename = webpackConfig.output.chunkFilename;
95+
if (chunkFilename && chunkFilename.includes('[name]')) {
96+
webpackConfig.output.chunkFilename = chunkFilename.replace('[name]', `${prefix}_${namespace}-[name]`);
97+
} else {
98+
webpackConfig.output.chunkFilename = `js/${prefix}_${namespace}-[name].[contenthash:8].js`;
99+
}
100+
101+
// TODO 提供方法对外补充一些修改
102+
return webpackConfig;
103+
});
104+
};
105+
106+
module.exports.configuration = {
107+
description: 'webpack 适配增强 config 配置信息',
108+
};

src/extends/submodule/methods.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
'use strict';
2+
3+
module.exports = api => {
4+
5+
// api.registerMethod('modifyDefaultServerConfig', {
6+
// type: api.API_TYPE.MODIFY,
7+
// description: '修改服务端配置合并事件',
8+
// });
9+
10+
};

src/extends/webpack/configCombine.js

Lines changed: 15 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,38 +3,28 @@
33
module.exports = function configCombine(obj) {
44

55
function pages() {
6-
7-
const entry = obj.entry;
6+
const entry = obj.entry || {};
7+
const html = obj.html || {}; // 优先
88
const htmls = obj.htmls || [];
9-
const html = Array.isArray(htmls) && htmls[0] || {};
10-
11-
if (typeof entry === 'object') {
12-
return Object.keys(entry).reduce((obj, key) => {
13-
const _entry = entry[key];
14-
const _html = htmls.find(item => Array.isArray(item.chunks) && item.chunks.includes(key)) || html;
15-
obj[key] = {
16-
entry: _entry,
17-
..._html,
18-
};
19-
return obj;
20-
}, {});
21-
}
22-
23-
return {
24-
index: {
25-
// page 的入口
26-
entry,
27-
...html,
28-
},
29-
};
9+
const _defaultHtml = Array.isArray(htmls) && htmls[0] || {};
10+
return Object.keys(entry).reduce((obj, key) => {
11+
const _entry = entry[key];
12+
const _html = html[key]
13+
|| htmls.find(item => Array.isArray(item.chunks) && item.chunks.includes(key)) || _defaultHtml; // 兼容
14+
obj[key] = {
15+
entry: _entry,
16+
..._html,
17+
};
18+
return obj;
19+
}, {});
3020
}
3121

3222
function nodeModulesPaths() {
3323
const nodeModulesPath = obj.nodeModulesPath;
3424
if (nodeModulesPath && !Array.isArray(nodeModulesPath)) {
35-
return [ nodeModulesPath ];
25+
return [ nodeModulesPath ].sort();
3626
} else if (Array.isArray(nodeModulesPath)) {
37-
return nodeModulesPath;
27+
return nodeModulesPath.sort();
3828
}
3929
return [];
4030
}

0 commit comments

Comments
 (0)