@modern-js/builder 2.4.1-beta.0 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +36 -3
- package/dist/plugins/html.d.ts +3 -0
- package/dist/plugins/html.js +213 -0
- package/dist/plugins/index.d.ts +1 -0
- package/dist/plugins/index.js +1 -0
- package/dist/plugins/startUrl.js +20 -3
- package/package.json +4 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,18 +1,51 @@
|
|
|
1
1
|
# @modern-js/builder
|
|
2
2
|
|
|
3
|
-
## 2.
|
|
3
|
+
## 2.6.0
|
|
4
4
|
|
|
5
5
|
### Patch Changes
|
|
6
6
|
|
|
7
|
+
- 107f674: feat(builder): add dev.beforeStartUrl config
|
|
8
|
+
|
|
9
|
+
feat(builder): 新增 dev.beforeStartUrl 配置项
|
|
10
|
+
|
|
11
|
+
- 0fe658a: feat(builder): support passing URL to html.favicon
|
|
12
|
+
|
|
13
|
+
feat(builder): 支持在 html.favicon 中直接传入 URL
|
|
14
|
+
|
|
15
|
+
- Updated dependencies [b92d6db]
|
|
16
|
+
- Updated dependencies [e1f799e]
|
|
17
|
+
- Updated dependencies [107f674]
|
|
18
|
+
- Updated dependencies [7915ab3]
|
|
19
|
+
- Updated dependencies [03d7f7d]
|
|
20
|
+
- Updated dependencies [fae9d1b]
|
|
21
|
+
- Updated dependencies [0fe658a]
|
|
22
|
+
- Updated dependencies [62930b9]
|
|
23
|
+
- @modern-js/builder-shared@2.6.0
|
|
24
|
+
- @modern-js/utils@2.6.0
|
|
25
|
+
|
|
26
|
+
## 2.5.0
|
|
27
|
+
|
|
28
|
+
### Patch Changes
|
|
29
|
+
|
|
30
|
+
- 442204a: fix(builder): should not open startUrl multiple times
|
|
31
|
+
|
|
32
|
+
fix(builder): 修复 startUrl 被重复打开的问题
|
|
33
|
+
|
|
34
|
+
- 30614fa: chore: modify package.json entry fields and build config
|
|
35
|
+
chore: 更改 package.json entry 字段以及构建配置
|
|
7
36
|
- c4c10e7: refactor: refactor rules for static assets processing with rule.oneOf, reuse svg/font/image/media plugin
|
|
8
37
|
|
|
9
38
|
refactor: 使用 oneOf 重构静态资源处理规则 & 复用 svg / font / media / img 插件
|
|
10
39
|
|
|
40
|
+
- Updated dependencies [58a9918]
|
|
41
|
+
- Updated dependencies [30614fa]
|
|
11
42
|
- Updated dependencies [c4c10e7]
|
|
43
|
+
- Updated dependencies [1b0ce87]
|
|
12
44
|
- Updated dependencies [11c053b]
|
|
13
45
|
- Updated dependencies [28e7dc6]
|
|
14
|
-
|
|
15
|
-
- @modern-js/
|
|
46
|
+
- Updated dependencies [40230b3]
|
|
47
|
+
- @modern-js/builder-shared@2.5.0
|
|
48
|
+
- @modern-js/utils@2.5.0
|
|
16
49
|
|
|
17
50
|
## 2.4.0
|
|
18
51
|
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.builderPluginHtml = exports.applyInjectTags = void 0;
|
|
30
|
+
const path_1 = __importDefault(require("path"));
|
|
31
|
+
const builder_shared_1 = require("@modern-js/builder-shared");
|
|
32
|
+
const lodash_1 = __importDefault(require("@modern-js/utils/lodash"));
|
|
33
|
+
async function getTemplateParameters(entryName, config, assetPrefix) {
|
|
34
|
+
const { applyOptionsChain } = await Promise.resolve().then(() => __importStar(require('@modern-js/utils')));
|
|
35
|
+
const { mountId, templateParameters, templateParametersByEntries } = config.html;
|
|
36
|
+
const meta = await (0, builder_shared_1.getMetaTags)(entryName, config);
|
|
37
|
+
const title = (0, builder_shared_1.getTitle)(entryName, config);
|
|
38
|
+
const templateParams = (templateParametersByEntries === null || templateParametersByEntries === void 0 ? void 0 : templateParametersByEntries[entryName]) || templateParameters;
|
|
39
|
+
const baseParameters = {
|
|
40
|
+
meta,
|
|
41
|
+
title,
|
|
42
|
+
mountId,
|
|
43
|
+
entryName,
|
|
44
|
+
assetPrefix,
|
|
45
|
+
};
|
|
46
|
+
return (compilation, assets, assetTags, pluginOptions) => {
|
|
47
|
+
const defaultOptions = {
|
|
48
|
+
compilation,
|
|
49
|
+
webpackConfig: compilation.options,
|
|
50
|
+
htmlWebpackPlugin: {
|
|
51
|
+
tags: assetTags,
|
|
52
|
+
files: assets,
|
|
53
|
+
options: pluginOptions,
|
|
54
|
+
},
|
|
55
|
+
...baseParameters,
|
|
56
|
+
};
|
|
57
|
+
return applyOptionsChain(defaultOptions, templateParams);
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
async function getChunks(entryName, entryValue) {
|
|
61
|
+
const { isPlainObject } = await Promise.resolve().then(() => __importStar(require('@modern-js/utils')));
|
|
62
|
+
const dependOn = [];
|
|
63
|
+
if (isPlainObject(entryValue)) {
|
|
64
|
+
// @ts-expect-error assume entry is an entry object
|
|
65
|
+
dependOn.push(...entryValue.dependOn);
|
|
66
|
+
}
|
|
67
|
+
return [...dependOn, entryName];
|
|
68
|
+
}
|
|
69
|
+
// Determine if the string is a favicon url
|
|
70
|
+
const isFaviconUrl = (str) => str.startsWith('http');
|
|
71
|
+
const applyInjectTags = (api) => {
|
|
72
|
+
api.modifyBundlerChain(async (chain, { HtmlPlugin, CHAIN_ID }) => {
|
|
73
|
+
const config = api.getNormalizedConfig();
|
|
74
|
+
const tags = lodash_1.default.castArray(config.html.tags).filter(Boolean);
|
|
75
|
+
const tagsByEntries = lodash_1.default.mapValues(config.html.tagsByEntries, tags => lodash_1.default.castArray(tags).filter(Boolean));
|
|
76
|
+
const shouldByEntries = lodash_1.default.some(tagsByEntries, 'length');
|
|
77
|
+
// skip if options is empty.
|
|
78
|
+
if (!tags.length && !shouldByEntries) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
// dynamic import.
|
|
82
|
+
const { HtmlTagsPlugin } = await Promise.resolve().then(() => __importStar(require('@modern-js/builder-shared')));
|
|
83
|
+
// const { HtmlTagsPlugin } = await import('../webpackPlugins/HtmlTagsPlugin');
|
|
84
|
+
// create shared options used for entry without specified options.
|
|
85
|
+
const sharedOptions = {
|
|
86
|
+
HtmlPlugin,
|
|
87
|
+
append: true,
|
|
88
|
+
hash: false,
|
|
89
|
+
publicPath: true,
|
|
90
|
+
tags,
|
|
91
|
+
};
|
|
92
|
+
// apply only one webpack plugin if `html.tagsByEntries` is empty.
|
|
93
|
+
if (tags.length && !shouldByEntries) {
|
|
94
|
+
chain
|
|
95
|
+
.plugin(CHAIN_ID.PLUGIN.HTML_TAGS)
|
|
96
|
+
.use(HtmlTagsPlugin, [sharedOptions]);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
// apply webpack plugin for each entries.
|
|
100
|
+
for (const [entry, filename] of Object.entries(api.getHTMLPaths())) {
|
|
101
|
+
const opts = { ...sharedOptions, includes: [filename] };
|
|
102
|
+
entry in tagsByEntries && (opts.tags = tagsByEntries[entry]);
|
|
103
|
+
chain
|
|
104
|
+
.plugin(`${CHAIN_ID.PLUGIN.HTML_TAGS}#${entry}`)
|
|
105
|
+
.use(HtmlTagsPlugin, [opts]);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
};
|
|
109
|
+
exports.applyInjectTags = applyInjectTags;
|
|
110
|
+
const builderPluginHtml = () => ({
|
|
111
|
+
name: 'builder-plugin-html',
|
|
112
|
+
setup(api) {
|
|
113
|
+
const routesInfo = [];
|
|
114
|
+
api.modifyBundlerChain(async (chain, { HtmlPlugin, isProd, CHAIN_ID, target }) => {
|
|
115
|
+
const config = api.getNormalizedConfig();
|
|
116
|
+
// if html is disabled or target is server, skip html plugin
|
|
117
|
+
if ((0, builder_shared_1.isHtmlDisabled)(config, target)) {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
const { removeTailSlash, applyOptionsChain } = await Promise.resolve().then(() => __importStar(require('@modern-js/utils')));
|
|
121
|
+
const minify = (0, builder_shared_1.getMinify)(isProd, config);
|
|
122
|
+
const assetPrefix = removeTailSlash(chain.output.get('publicPath') || '');
|
|
123
|
+
const entries = chain.entryPoints.entries() || {};
|
|
124
|
+
const entryNames = Object.keys(entries);
|
|
125
|
+
const htmlPaths = api.getHTMLPaths();
|
|
126
|
+
const faviconUrls = [];
|
|
127
|
+
await Promise.all(entryNames.map(async (entryName, index) => {
|
|
128
|
+
const entryValue = entries[entryName].values();
|
|
129
|
+
const chunks = await getChunks(entryName, entryValue);
|
|
130
|
+
const inject = (0, builder_shared_1.getInject)(entryName, config);
|
|
131
|
+
const favicon = (0, builder_shared_1.getFavicon)(entryName, config);
|
|
132
|
+
const filename = htmlPaths[entryName];
|
|
133
|
+
const template = (0, builder_shared_1.getTemplatePath)(entryName, config);
|
|
134
|
+
const templateParameters = await getTemplateParameters(entryName, config, assetPrefix);
|
|
135
|
+
const pluginOptions = {
|
|
136
|
+
chunks,
|
|
137
|
+
inject,
|
|
138
|
+
minify,
|
|
139
|
+
filename,
|
|
140
|
+
template,
|
|
141
|
+
templateParameters,
|
|
142
|
+
};
|
|
143
|
+
if (favicon) {
|
|
144
|
+
if (isFaviconUrl(favicon)) {
|
|
145
|
+
faviconUrls.push({
|
|
146
|
+
filename,
|
|
147
|
+
url: favicon,
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
// HTMLWebpackPlugin only support favicon file path
|
|
152
|
+
pluginOptions.favicon = favicon;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
const finalOptions = applyOptionsChain(pluginOptions, config.tools.htmlPlugin, {
|
|
156
|
+
entryName,
|
|
157
|
+
entryValue,
|
|
158
|
+
});
|
|
159
|
+
routesInfo.push({
|
|
160
|
+
urlPath: index === 0 ? '/' : `/${entryName}`,
|
|
161
|
+
entryName,
|
|
162
|
+
entryPath: filename,
|
|
163
|
+
isSPA: true,
|
|
164
|
+
});
|
|
165
|
+
chain
|
|
166
|
+
.plugin(`${CHAIN_ID.PLUGIN.HTML}-${entryName}`)
|
|
167
|
+
.use(HtmlPlugin, [finalOptions]);
|
|
168
|
+
}));
|
|
169
|
+
if (config.html) {
|
|
170
|
+
const { appIcon, crossorigin } = config.html;
|
|
171
|
+
if (crossorigin) {
|
|
172
|
+
const { HtmlCrossOriginPlugin } = await Promise.resolve().then(() => __importStar(require('@modern-js/builder-shared')));
|
|
173
|
+
const formattedCrossorigin = crossorigin === true ? 'anonymous' : crossorigin;
|
|
174
|
+
chain
|
|
175
|
+
.plugin(CHAIN_ID.PLUGIN.HTML_CROSS_ORIGIN)
|
|
176
|
+
.use(HtmlCrossOriginPlugin, [
|
|
177
|
+
{ crossOrigin: formattedCrossorigin, HtmlPlugin },
|
|
178
|
+
]);
|
|
179
|
+
// todo: not support in rspack
|
|
180
|
+
// @ts-expect-error
|
|
181
|
+
chain.output.crossOriginLoading(formattedCrossorigin);
|
|
182
|
+
}
|
|
183
|
+
if (faviconUrls.length) {
|
|
184
|
+
const { HtmlFaviconUrlPlugin } = await Promise.resolve().then(() => __importStar(require('@modern-js/builder-shared')));
|
|
185
|
+
chain
|
|
186
|
+
.plugin(CHAIN_ID.PLUGIN.FAVICON_URL)
|
|
187
|
+
.use(HtmlFaviconUrlPlugin, [{ faviconUrls, HtmlPlugin }]);
|
|
188
|
+
}
|
|
189
|
+
if (appIcon) {
|
|
190
|
+
const { HtmlAppIconPlugin } = await Promise.resolve().then(() => __importStar(require('@modern-js/builder-shared')));
|
|
191
|
+
const distDir = (0, builder_shared_1.getDistPath)(config.output, 'image');
|
|
192
|
+
const iconPath = path_1.default.isAbsolute(appIcon)
|
|
193
|
+
? appIcon
|
|
194
|
+
: path_1.default.join(api.context.rootPath, appIcon);
|
|
195
|
+
chain
|
|
196
|
+
.plugin(CHAIN_ID.PLUGIN.APP_ICON)
|
|
197
|
+
.use(HtmlAppIconPlugin, [{ iconPath, distDir, HtmlPlugin }]);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
api.onBeforeStartDevServer(async () => {
|
|
202
|
+
const { fs, ROUTE_SPEC_FILE } = await Promise.resolve().then(() => __importStar(require('@modern-js/utils')));
|
|
203
|
+
const routeFilePath = path_1.default.join(api.context.distPath, ROUTE_SPEC_FILE);
|
|
204
|
+
// generate a basic route.json for modern.js dev server
|
|
205
|
+
// if the framework has already generate a route.json, do nothing
|
|
206
|
+
if (!(await (0, builder_shared_1.isFileExists)(routeFilePath)) && routesInfo.length) {
|
|
207
|
+
await fs.outputFile(routeFilePath, JSON.stringify({ routes: routesInfo }, null, 2));
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
(0, exports.applyInjectTags)(api);
|
|
211
|
+
},
|
|
212
|
+
});
|
|
213
|
+
exports.builderPluginHtml = builderPluginHtml;
|
package/dist/plugins/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export declare const plugins: {
|
|
2
|
+
html: () => Promise<import("@modern-js/builder-shared").DefaultBuilderPlugin>;
|
|
2
3
|
cleanOutput: () => Promise<import("@modern-js/builder-shared").DefaultBuilderPlugin>;
|
|
3
4
|
startUrl: () => Promise<import("@modern-js/builder-shared").DefaultBuilderPlugin>;
|
|
4
5
|
fileSize: () => Promise<import("@modern-js/builder-shared").DefaultBuilderPlugin>;
|
package/dist/plugins/index.js
CHANGED
|
@@ -26,6 +26,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
26
26
|
exports.plugins = void 0;
|
|
27
27
|
const builder_shared_1 = require("@modern-js/builder-shared");
|
|
28
28
|
exports.plugins = {
|
|
29
|
+
html: () => Promise.resolve().then(() => __importStar(require('./html'))).then(m => m.builderPluginHtml()),
|
|
29
30
|
cleanOutput: () => Promise.resolve().then(() => __importStar(require('./cleanOutput'))).then(m => m.builderPluginCleanOutput()),
|
|
30
31
|
startUrl: () => Promise.resolve().then(() => __importStar(require('./startUrl'))).then(m => m.builderPluginStartUrl()),
|
|
31
32
|
fileSize: () => Promise.resolve().then(() => __importStar(require('./fileSize'))).then(m => m.builderPluginFileSize()),
|
package/dist/plugins/startUrl.js
CHANGED
|
@@ -30,6 +30,7 @@ exports.builderPluginStartUrl = exports.replacePlaceholder = void 0;
|
|
|
30
30
|
const lodash_1 = __importDefault(require("@modern-js/utils/lodash"));
|
|
31
31
|
const replacePlaceholder = (url, port) => url.replace(/<port>/g, String(port));
|
|
32
32
|
exports.replacePlaceholder = replacePlaceholder;
|
|
33
|
+
const openedURLs = [];
|
|
33
34
|
function builderPluginStartUrl() {
|
|
34
35
|
return {
|
|
35
36
|
name: 'builder-plugin-start-url',
|
|
@@ -43,7 +44,7 @@ function builderPluginStartUrl() {
|
|
|
43
44
|
return;
|
|
44
45
|
}
|
|
45
46
|
const config = api.getNormalizedConfig();
|
|
46
|
-
const { https, startUrl } = config.dev;
|
|
47
|
+
const { https, startUrl, beforeStartUrl } = config.dev;
|
|
47
48
|
if (!startUrl) {
|
|
48
49
|
return;
|
|
49
50
|
}
|
|
@@ -55,9 +56,25 @@ function builderPluginStartUrl() {
|
|
|
55
56
|
else {
|
|
56
57
|
urls.push(...lodash_1.default.castArray(startUrl).map(item => (0, exports.replacePlaceholder)(item, port)));
|
|
57
58
|
}
|
|
59
|
+
const { ensureArray } = await Promise.resolve().then(() => __importStar(require('@modern-js/utils')));
|
|
58
60
|
const { openBrowser } = await Promise.resolve().then(() => __importStar(require('@modern-js/builder-shared')));
|
|
59
|
-
|
|
60
|
-
|
|
61
|
+
const openUrls = () => {
|
|
62
|
+
for (const url of urls) {
|
|
63
|
+
/**
|
|
64
|
+
* If a URL has been opened in current process, we will not open it again.
|
|
65
|
+
* It can prevent opening the same URL multiple times.
|
|
66
|
+
*/
|
|
67
|
+
if (!openedURLs.includes(url)) {
|
|
68
|
+
openBrowser(url);
|
|
69
|
+
openedURLs.push(url);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
if (beforeStartUrl) {
|
|
74
|
+
Promise.all(ensureArray(beforeStartUrl).map(fn => fn())).then(openUrls);
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
openUrls();
|
|
61
78
|
}
|
|
62
79
|
});
|
|
63
80
|
},
|
package/package.json
CHANGED
|
@@ -14,12 +14,11 @@
|
|
|
14
14
|
"engines": {
|
|
15
15
|
"node": ">=14.0.0"
|
|
16
16
|
},
|
|
17
|
-
"version": "2.
|
|
17
|
+
"version": "2.6.0",
|
|
18
18
|
"jsnext:source": "./src/index.ts",
|
|
19
19
|
"types": "./dist/index.d.ts",
|
|
20
20
|
"main": "./dist/index.js",
|
|
21
21
|
"module": "./dist/index.js",
|
|
22
|
-
"jsnext:modern": "./dist/index.js",
|
|
23
22
|
"exports": {
|
|
24
23
|
".": {
|
|
25
24
|
"jsnext:source": "./src/index.ts",
|
|
@@ -28,8 +27,8 @@
|
|
|
28
27
|
},
|
|
29
28
|
"dependencies": {
|
|
30
29
|
"@svgr/webpack": "6.5.1",
|
|
31
|
-
"@modern-js/builder-shared": "2.
|
|
32
|
-
"@modern-js/utils": "2.
|
|
30
|
+
"@modern-js/builder-shared": "2.6.0",
|
|
31
|
+
"@modern-js/utils": "2.6.0"
|
|
33
32
|
},
|
|
34
33
|
"devDependencies": {
|
|
35
34
|
"@babel/core": "7.18.0",
|
|
@@ -37,7 +36,7 @@
|
|
|
37
36
|
"@types/babel__preset-env": "^7.9.2",
|
|
38
37
|
"@types/node": "^14",
|
|
39
38
|
"typescript": "^4",
|
|
40
|
-
"@scripts/vitest-config": "2.
|
|
39
|
+
"@scripts/vitest-config": "2.6.0"
|
|
41
40
|
},
|
|
42
41
|
"publishConfig": {
|
|
43
42
|
"registry": "https://registry.npmjs.org/",
|