@nx/webpack 0.0.0-pr-22179-271588f
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/LICENSE +22 -0
- package/README.md +68 -0
- package/executors.json +19 -0
- package/generators.json +20 -0
- package/index.d.ts +18 -0
- package/index.js +24 -0
- package/migrations.json +60 -0
- package/package.json +74 -0
- package/plugin.d.ts +1 -0
- package/plugin.js +5 -0
- package/src/executors/dev-server/dev-server.impl.d.ts +7 -0
- package/src/executors/dev-server/dev-server.impl.js +79 -0
- package/src/executors/dev-server/lib/get-dev-server-config.d.ts +4 -0
- package/src/executors/dev-server/lib/get-dev-server-config.js +79 -0
- package/src/executors/dev-server/lib/serve-path.d.ts +3 -0
- package/src/executors/dev-server/lib/serve-path.js +45 -0
- package/src/executors/dev-server/schema.d.ts +17 -0
- package/src/executors/dev-server/schema.json +76 -0
- package/src/executors/ssr-dev-server/lib/wait-until-server-is-listening.d.ts +1 -0
- package/src/executors/ssr-dev-server/lib/wait-until-server-is-listening.js +39 -0
- package/src/executors/ssr-dev-server/schema.d.ts +11 -0
- package/src/executors/ssr-dev-server/schema.json +37 -0
- package/src/executors/ssr-dev-server/ssr-dev-server.impl.d.ts +8 -0
- package/src/executors/ssr-dev-server/ssr-dev-server.impl.js +39 -0
- package/src/executors/webpack/lib/normalize-options.d.ts +3 -0
- package/src/executors/webpack/lib/normalize-options.js +40 -0
- package/src/executors/webpack/lib/run-webpack.d.ts +3 -0
- package/src/executors/webpack/lib/run-webpack.js +36 -0
- package/src/executors/webpack/schema.d.ts +96 -0
- package/src/executors/webpack/schema.json +394 -0
- package/src/executors/webpack/webpack.impl.d.ts +13 -0
- package/src/executors/webpack/webpack.impl.js +125 -0
- package/src/generators/configuration/configuration.d.ts +5 -0
- package/src/generators/configuration/configuration.js +194 -0
- package/src/generators/configuration/schema.d.ts +14 -0
- package/src/generators/configuration/schema.json +77 -0
- package/src/generators/init/init.d.ts +5 -0
- package/src/generators/init/init.js +60 -0
- package/src/generators/init/schema.d.ts +7 -0
- package/src/generators/init/schema.json +33 -0
- package/src/migrations/update-15-0-0/add-babel-inputs.d.ts +2 -0
- package/src/migrations/update-15-0-0/add-babel-inputs.js +9 -0
- package/src/migrations/update-15-4-5/remove-es2015-polyfills-option.d.ts +2 -0
- package/src/migrations/update-15-4-5/remove-es2015-polyfills-option.js +20 -0
- package/src/migrations/update-15-6-3/webpack-config-setup.d.ts +2 -0
- package/src/migrations/update-15-6-3/webpack-config-setup.js +100 -0
- package/src/migrations/update-15-7-2/add-babelUpwardRootMode-flag.d.ts +2 -0
- package/src/migrations/update-15-7-2/add-babelUpwardRootMode-flag.js +17 -0
- package/src/migrations/update-16-0-0-add-nx-packages/update-16-0-0-add-nx-packages.d.ts +2 -0
- package/src/migrations/update-16-0-0-add-nx-packages/update-16-0-0-add-nx-packages.js +9 -0
- package/src/migrations/update-17-2-1/webpack-config-setup.d.ts +2 -0
- package/src/migrations/update-17-2-1/webpack-config-setup.js +31 -0
- package/src/plugins/generate-package-json-plugin.d.ts +14 -0
- package/src/plugins/generate-package-json-plugin.js +44 -0
- package/src/plugins/nx-typescript-webpack-plugin/nx-tsconfig-paths-webpack-plugin.d.ts +8 -0
- package/src/plugins/nx-typescript-webpack-plugin/nx-tsconfig-paths-webpack-plugin.js +31 -0
- package/src/plugins/nx-webpack-plugin/lib/apply-base-config.d.ts +5 -0
- package/src/plugins/nx-webpack-plugin/lib/apply-base-config.js +318 -0
- package/src/plugins/nx-webpack-plugin/lib/apply-web-config.d.ts +5 -0
- package/src/plugins/nx-webpack-plugin/lib/apply-web-config.js +372 -0
- package/src/plugins/nx-webpack-plugin/lib/compiler-loaders.d.ts +53 -0
- package/src/plugins/nx-webpack-plugin/lib/compiler-loaders.js +78 -0
- package/src/plugins/nx-webpack-plugin/lib/get-terser-ecma-version.d.ts +1 -0
- package/src/plugins/nx-webpack-plugin/lib/get-terser-ecma-version.js +35 -0
- package/src/plugins/nx-webpack-plugin/lib/instantiate-script-plugins.d.ts +3 -0
- package/src/plugins/nx-webpack-plugin/lib/instantiate-script-plugins.js +42 -0
- package/src/plugins/nx-webpack-plugin/lib/normalize-options.d.ts +4 -0
- package/src/plugins/nx-webpack-plugin/lib/normalize-options.js +143 -0
- package/src/plugins/nx-webpack-plugin/lib/stylesheet-loaders.d.ts +73 -0
- package/src/plugins/nx-webpack-plugin/lib/stylesheet-loaders.js +117 -0
- package/src/plugins/nx-webpack-plugin/nx-webpack-plugin-options.d.ts +216 -0
- package/src/plugins/nx-webpack-plugin/nx-webpack-plugin-options.js +2 -0
- package/src/plugins/nx-webpack-plugin/nx-webpack-plugin.d.ts +17 -0
- package/src/plugins/nx-webpack-plugin/nx-webpack-plugin.js +48 -0
- package/src/plugins/plugin.d.ts +9 -0
- package/src/plugins/plugin.js +131 -0
- package/src/plugins/stats-json-plugin.d.ts +4 -0
- package/src/plugins/stats-json-plugin.js +13 -0
- package/src/plugins/webpack-nx-build-coordination-plugin.d.ts +11 -0
- package/src/plugins/webpack-nx-build-coordination-plugin.js +85 -0
- package/src/plugins/write-index-html-plugin.d.ts +22 -0
- package/src/plugins/write-index-html-plugin.js +249 -0
- package/src/utils/config.d.ts +22 -0
- package/src/utils/config.js +66 -0
- package/src/utils/create-copy-plugin.d.ts +3 -0
- package/src/utils/create-copy-plugin.js +26 -0
- package/src/utils/ensure-dependencies.d.ts +6 -0
- package/src/utils/ensure-dependencies.js +28 -0
- package/src/utils/fs.d.ts +6 -0
- package/src/utils/fs.js +58 -0
- package/src/utils/get-client-environment.d.ts +5 -0
- package/src/utils/get-client-environment.js +29 -0
- package/src/utils/get-css-module-local-ident.d.ts +1 -0
- package/src/utils/get-css-module-local-ident.js +18 -0
- package/src/utils/has-plugin.d.ts +2 -0
- package/src/utils/has-plugin.js +11 -0
- package/src/utils/hash-format.d.ts +7 -0
- package/src/utils/hash-format.js +23 -0
- package/src/utils/models.d.ts +23 -0
- package/src/utils/models.js +2 -0
- package/src/utils/module-federation/dependencies.d.ts +6 -0
- package/src/utils/module-federation/dependencies.js +57 -0
- package/src/utils/module-federation/get-remotes-for-host.d.ts +14 -0
- package/src/utils/module-federation/get-remotes-for-host.js +88 -0
- package/src/utils/module-federation/index.d.ts +6 -0
- package/src/utils/module-federation/index.js +9 -0
- package/src/utils/module-federation/models/index.d.ts +39 -0
- package/src/utils/module-federation/models/index.js +2 -0
- package/src/utils/module-federation/package-json.d.ts +8 -0
- package/src/utils/module-federation/package-json.js +13 -0
- package/src/utils/module-federation/public-api.d.ts +6 -0
- package/src/utils/module-federation/public-api.js +16 -0
- package/src/utils/module-federation/remotes.d.ts +19 -0
- package/src/utils/module-federation/remotes.js +80 -0
- package/src/utils/module-federation/secondary-entry-points.d.ts +12 -0
- package/src/utils/module-federation/secondary-entry-points.js +108 -0
- package/src/utils/module-federation/share.d.ts +48 -0
- package/src/utils/module-federation/share.js +215 -0
- package/src/utils/module-federation/typescript.d.ts +4 -0
- package/src/utils/module-federation/typescript.js +54 -0
- package/src/utils/run-webpack.d.ts +5 -0
- package/src/utils/run-webpack.js +31 -0
- package/src/utils/versions.d.ts +8 -0
- package/src/utils/versions.js +12 -0
- package/src/utils/web-babel-loader.d.ts +0 -0
- package/src/utils/web-babel-loader.js +17 -0
- package/src/utils/webpack/deprecated-stylus-loader.d.ts +1 -0
- package/src/utils/webpack/deprecated-stylus-loader.js +11 -0
- package/src/utils/webpack/interpolate-env-variables-to-index.d.ts +1 -0
- package/src/utils/webpack/interpolate-env-variables-to-index.js +30 -0
- package/src/utils/webpack/normalize-entry.d.ts +2 -0
- package/src/utils/webpack/normalize-entry.js +28 -0
- package/src/utils/webpack/package-chunk-sort.d.ts +5 -0
- package/src/utils/webpack/package-chunk-sort.js +29 -0
- package/src/utils/webpack/plugins/postcss-cli-resources.d.ts +13 -0
- package/src/utils/webpack/plugins/postcss-cli-resources.js +165 -0
- package/src/utils/webpack/plugins/scripts-webpack-plugin.d.ts +17 -0
- package/src/utils/webpack/plugins/scripts-webpack-plugin.js +119 -0
- package/src/utils/webpack/read-webpack-options.d.ts +10 -0
- package/src/utils/webpack/read-webpack-options.js +41 -0
- package/src/utils/webpack/resolve-user-defined-webpack-config.d.ts +3 -0
- package/src/utils/webpack/resolve-user-defined-webpack-config.js +39 -0
- package/src/utils/with-nx.d.ts +8 -0
- package/src/utils/with-nx.js +34 -0
- package/src/utils/with-web.d.ts +22 -0
- package/src/utils/with-web.js +26 -0
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createNodes = exports.createDependencies = void 0;
|
|
4
|
+
const devkit_1 = require("@nx/devkit");
|
|
5
|
+
const path_1 = require("path");
|
|
6
|
+
const get_named_inputs_1 = require("@nx/devkit/src/utils/get-named-inputs");
|
|
7
|
+
const fs_1 = require("fs");
|
|
8
|
+
const read_webpack_options_1 = require("../utils/webpack/read-webpack-options");
|
|
9
|
+
const resolve_user_defined_webpack_config_1 = require("../utils/webpack/resolve-user-defined-webpack-config");
|
|
10
|
+
const js_1 = require("@nx/js");
|
|
11
|
+
const cache_directory_1 = require("nx/src/utils/cache-directory");
|
|
12
|
+
const calculate_hash_for_create_nodes_1 = require("@nx/devkit/src/utils/calculate-hash-for-create-nodes");
|
|
13
|
+
const cachePath = (0, path_1.join)(cache_directory_1.projectGraphCacheDirectory, 'webpack.hash');
|
|
14
|
+
const targetsCache = (0, fs_1.existsSync)(cachePath) ? readTargetsCache() : {};
|
|
15
|
+
const calculatedTargets = {};
|
|
16
|
+
function readTargetsCache() {
|
|
17
|
+
return (0, devkit_1.readJsonFile)(cachePath);
|
|
18
|
+
}
|
|
19
|
+
function writeTargetsToCache(targets) {
|
|
20
|
+
(0, devkit_1.writeJsonFile)(cachePath, targets);
|
|
21
|
+
}
|
|
22
|
+
const createDependencies = () => {
|
|
23
|
+
writeTargetsToCache(calculatedTargets);
|
|
24
|
+
return [];
|
|
25
|
+
};
|
|
26
|
+
exports.createDependencies = createDependencies;
|
|
27
|
+
exports.createNodes = [
|
|
28
|
+
'**/webpack.config.{js,ts,mjs,cjs}',
|
|
29
|
+
async (configFilePath, options, context) => {
|
|
30
|
+
options ??= {};
|
|
31
|
+
options.buildTargetName ??= 'build';
|
|
32
|
+
options.serveTargetName ??= 'serve';
|
|
33
|
+
options.serveStaticTargetName ??= 'serve-static';
|
|
34
|
+
options.previewTargetName ??= 'preview';
|
|
35
|
+
const projectRoot = (0, path_1.dirname)(configFilePath);
|
|
36
|
+
// Do not create a project if package.json and project.json isn't there.
|
|
37
|
+
const siblingFiles = (0, fs_1.readdirSync)((0, path_1.join)(context.workspaceRoot, projectRoot));
|
|
38
|
+
if (!siblingFiles.includes('package.json') &&
|
|
39
|
+
!siblingFiles.includes('project.json')) {
|
|
40
|
+
return {};
|
|
41
|
+
}
|
|
42
|
+
const hash = (0, calculate_hash_for_create_nodes_1.calculateHashForCreateNodes)(projectRoot, options, context, [
|
|
43
|
+
(0, js_1.getLockFileName)((0, devkit_1.detectPackageManager)(context.workspaceRoot)),
|
|
44
|
+
]);
|
|
45
|
+
const targets = targetsCache[hash]
|
|
46
|
+
? targetsCache[hash]
|
|
47
|
+
: await createWebpackTargets(configFilePath, projectRoot, options, context);
|
|
48
|
+
return {
|
|
49
|
+
projects: {
|
|
50
|
+
[projectRoot]: {
|
|
51
|
+
projectType: 'application',
|
|
52
|
+
targets,
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
},
|
|
57
|
+
];
|
|
58
|
+
async function createWebpackTargets(configFilePath, projectRoot, options, context) {
|
|
59
|
+
const namedInputs = (0, get_named_inputs_1.getNamedInputs)(projectRoot, context);
|
|
60
|
+
const webpackConfig = (0, resolve_user_defined_webpack_config_1.resolveUserDefinedWebpackConfig)((0, path_1.join)(context.workspaceRoot, configFilePath), (0, js_1.getRootTsConfigPath)(), true);
|
|
61
|
+
const webpackOptions = await (0, read_webpack_options_1.readWebpackOptions)(webpackConfig);
|
|
62
|
+
const outputPath = normalizeOutputPath(webpackOptions.output?.path, projectRoot);
|
|
63
|
+
const targets = {};
|
|
64
|
+
targets[options.buildTargetName] = {
|
|
65
|
+
command: `webpack-cli build`,
|
|
66
|
+
options: { cwd: projectRoot, args: ['--node-env=production'] },
|
|
67
|
+
cache: true,
|
|
68
|
+
dependsOn: [`^${options.buildTargetName}`],
|
|
69
|
+
inputs: 'production' in namedInputs
|
|
70
|
+
? [
|
|
71
|
+
'production',
|
|
72
|
+
'^production',
|
|
73
|
+
{
|
|
74
|
+
externalDependencies: ['webpack-cli'],
|
|
75
|
+
},
|
|
76
|
+
]
|
|
77
|
+
: [
|
|
78
|
+
'default',
|
|
79
|
+
'^default',
|
|
80
|
+
{
|
|
81
|
+
externalDependencies: ['webpack-cli'],
|
|
82
|
+
},
|
|
83
|
+
],
|
|
84
|
+
outputs: [outputPath],
|
|
85
|
+
};
|
|
86
|
+
targets[options.serveTargetName] = {
|
|
87
|
+
command: `webpack-cli serve`,
|
|
88
|
+
options: {
|
|
89
|
+
cwd: projectRoot,
|
|
90
|
+
args: ['--node-env=development'],
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
targets[options.previewTargetName] = {
|
|
94
|
+
command: `webpack-cli serve`,
|
|
95
|
+
options: {
|
|
96
|
+
cwd: projectRoot,
|
|
97
|
+
args: ['--node-env=production'],
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
targets[options.serveStaticTargetName] = {
|
|
101
|
+
executor: '@nx/web:file-server',
|
|
102
|
+
options: {
|
|
103
|
+
buildTarget: options.buildTargetName,
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
return targets;
|
|
107
|
+
}
|
|
108
|
+
function normalizeOutputPath(outputPath, projectRoot) {
|
|
109
|
+
if (!outputPath) {
|
|
110
|
+
// If outputPath is undefined, use webpack's default `dist` directory.
|
|
111
|
+
if (projectRoot === '.') {
|
|
112
|
+
return `{projectRoot}/dist}`;
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
return `{workspaceRoot}/dist/{projectRoot}`;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
if ((0, path_1.isAbsolute)(outputPath)) {
|
|
120
|
+
return `{workspaceRoot}/${(0, path_1.relative)(devkit_1.workspaceRoot, outputPath)}`;
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
if (outputPath.startsWith('..')) {
|
|
124
|
+
return (0, path_1.join)('{workspaceRoot}', (0, path_1.join)(projectRoot, outputPath));
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
return (0, path_1.join)('{projectRoot}', outputPath);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.StatsJsonPlugin = void 0;
|
|
4
|
+
const webpack_1 = require("webpack");
|
|
5
|
+
class StatsJsonPlugin {
|
|
6
|
+
apply(compiler) {
|
|
7
|
+
compiler.hooks.emit.tap('StatsJsonPlugin', (compilation) => {
|
|
8
|
+
const data = JSON.stringify(compilation.getStats().toJson('verbose'));
|
|
9
|
+
compilation.assets[`stats.json`] = new webpack_1.sources.RawSource(data);
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
exports.StatsJsonPlugin = StatsJsonPlugin;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Compiler } from 'webpack';
|
|
2
|
+
export declare class WebpackNxBuildCoordinationPlugin {
|
|
3
|
+
private readonly buildCmd;
|
|
4
|
+
private currentlyRunning;
|
|
5
|
+
private buildCmdProcess;
|
|
6
|
+
constructor(buildCmd: string, skipInitialBuild?: boolean);
|
|
7
|
+
apply(compiler: Compiler): void;
|
|
8
|
+
startWatchingBuildableLibs(): Promise<void>;
|
|
9
|
+
buildChangedProjects(): Promise<void>;
|
|
10
|
+
private createFileWatcher;
|
|
11
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.WebpackNxBuildCoordinationPlugin = void 0;
|
|
4
|
+
const child_process_1 = require("child_process");
|
|
5
|
+
const client_1 = require("nx/src/daemon/client/client");
|
|
6
|
+
const watch_1 = require("nx/src/command-line/watch");
|
|
7
|
+
const output_1 = require("nx/src/utils/output");
|
|
8
|
+
class WebpackNxBuildCoordinationPlugin {
|
|
9
|
+
constructor(buildCmd, skipInitialBuild) {
|
|
10
|
+
this.buildCmd = buildCmd;
|
|
11
|
+
this.currentlyRunning = 'none';
|
|
12
|
+
this.buildCmdProcess = null;
|
|
13
|
+
if (!skipInitialBuild) {
|
|
14
|
+
this.buildChangedProjects();
|
|
15
|
+
}
|
|
16
|
+
this.startWatchingBuildableLibs();
|
|
17
|
+
}
|
|
18
|
+
apply(compiler) {
|
|
19
|
+
compiler.hooks.beforeCompile.tapPromise('IncrementalDevServerPlugin', async () => {
|
|
20
|
+
while (this.currentlyRunning === 'nx-build') {
|
|
21
|
+
await sleep(50);
|
|
22
|
+
}
|
|
23
|
+
this.currentlyRunning = 'webpack-build';
|
|
24
|
+
});
|
|
25
|
+
compiler.hooks.done.tapPromise('IncrementalDevServerPlugin', async () => {
|
|
26
|
+
this.currentlyRunning = 'none';
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
async startWatchingBuildableLibs() {
|
|
30
|
+
const unregisterFileWatcher = await this.createFileWatcher();
|
|
31
|
+
process.on('exit', () => {
|
|
32
|
+
unregisterFileWatcher();
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
async buildChangedProjects() {
|
|
36
|
+
while (this.currentlyRunning === 'webpack-build') {
|
|
37
|
+
await sleep(50);
|
|
38
|
+
}
|
|
39
|
+
this.currentlyRunning = 'nx-build';
|
|
40
|
+
try {
|
|
41
|
+
return await new Promise((res) => {
|
|
42
|
+
this.buildCmdProcess = (0, child_process_1.exec)(this.buildCmd);
|
|
43
|
+
this.buildCmdProcess.stdout.pipe(process.stdout);
|
|
44
|
+
this.buildCmdProcess.stderr.pipe(process.stderr);
|
|
45
|
+
this.buildCmdProcess.on('exit', () => {
|
|
46
|
+
res();
|
|
47
|
+
});
|
|
48
|
+
this.buildCmdProcess.on('error', () => {
|
|
49
|
+
res();
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
finally {
|
|
54
|
+
this.currentlyRunning = 'none';
|
|
55
|
+
this.buildCmdProcess = null;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
createFileWatcher() {
|
|
59
|
+
const runner = new watch_1.BatchFunctionRunner(() => this.buildChangedProjects());
|
|
60
|
+
return client_1.daemonClient.registerFileWatcher({
|
|
61
|
+
watchProjects: 'all',
|
|
62
|
+
}, (err, { changedProjects, changedFiles }) => {
|
|
63
|
+
if (err === 'closed') {
|
|
64
|
+
output_1.output.error({
|
|
65
|
+
title: 'Watch connection closed',
|
|
66
|
+
bodyLines: [
|
|
67
|
+
'The daemon has closed the connection to this watch process.',
|
|
68
|
+
'Please restart your watch command.',
|
|
69
|
+
],
|
|
70
|
+
});
|
|
71
|
+
process.exit(1);
|
|
72
|
+
}
|
|
73
|
+
if (this.buildCmdProcess) {
|
|
74
|
+
this.buildCmdProcess.kill(2);
|
|
75
|
+
this.buildCmdProcess = null;
|
|
76
|
+
}
|
|
77
|
+
// Queue a build
|
|
78
|
+
runner.enqueue(changedProjects, changedFiles);
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
exports.WebpackNxBuildCoordinationPlugin = WebpackNxBuildCoordinationPlugin;
|
|
83
|
+
function sleep(time) {
|
|
84
|
+
return new Promise((resolve) => setTimeout(resolve, time));
|
|
85
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Compiler } from 'webpack';
|
|
2
|
+
import { ExtraEntryPoint } from '../utils/models';
|
|
3
|
+
export interface WriteIndexHtmlOptions {
|
|
4
|
+
indexPath: string;
|
|
5
|
+
outputPath: string;
|
|
6
|
+
baseHref?: string;
|
|
7
|
+
deployUrl?: string;
|
|
8
|
+
sri?: boolean;
|
|
9
|
+
scripts?: ExtraEntryPoint[];
|
|
10
|
+
styles?: ExtraEntryPoint[];
|
|
11
|
+
crossOrigin?: 'none' | 'anonymous' | 'use-credentials';
|
|
12
|
+
}
|
|
13
|
+
export declare class WriteIndexHtmlPlugin {
|
|
14
|
+
private readonly options;
|
|
15
|
+
constructor(options: WriteIndexHtmlOptions);
|
|
16
|
+
apply(compiler: Compiler): void;
|
|
17
|
+
private getEmittedFiles;
|
|
18
|
+
private stripBom;
|
|
19
|
+
private augmentIndexHtml;
|
|
20
|
+
private generateSriAttributes;
|
|
21
|
+
private filterAndMapBuildFiles;
|
|
22
|
+
}
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.WriteIndexHtmlPlugin = void 0;
|
|
4
|
+
const webpack = require("webpack");
|
|
5
|
+
const crypto_1 = require("crypto");
|
|
6
|
+
const fs_1 = require("fs");
|
|
7
|
+
const interpolate_env_variables_to_index_1 = require("../utils/webpack/interpolate-env-variables-to-index");
|
|
8
|
+
const package_chunk_sort_1 = require("../utils/webpack/package-chunk-sort");
|
|
9
|
+
const path_1 = require("path");
|
|
10
|
+
const parse5 = require('parse5');
|
|
11
|
+
class WriteIndexHtmlPlugin {
|
|
12
|
+
constructor(options) {
|
|
13
|
+
this.options = options;
|
|
14
|
+
}
|
|
15
|
+
apply(compiler) {
|
|
16
|
+
const { outputPath, indexPath, baseHref, deployUrl, sri = false, scripts = [], styles = [], crossOrigin, } = this.options;
|
|
17
|
+
compiler.hooks.thisCompilation.tap('WriteIndexHtmlPlugin', (compilation) => {
|
|
18
|
+
compilation.hooks.processAssets.tap({
|
|
19
|
+
name: 'WriteIndexHtmlPlugin',
|
|
20
|
+
// After minification and sourcemaps are done
|
|
21
|
+
stage: webpack.Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_INLINE,
|
|
22
|
+
}, () => {
|
|
23
|
+
const moduleFiles = this.getEmittedFiles(compilation);
|
|
24
|
+
const files = moduleFiles.filter((x) => x.extension === '.css');
|
|
25
|
+
let content = (0, fs_1.readFileSync)(indexPath).toString();
|
|
26
|
+
content = this.stripBom(content);
|
|
27
|
+
compilation.assets[outputPath] = this.augmentIndexHtml({
|
|
28
|
+
input: outputPath,
|
|
29
|
+
inputContent: (0, interpolate_env_variables_to_index_1.interpolateEnvironmentVariablesToIndex)(content, deployUrl),
|
|
30
|
+
baseHref,
|
|
31
|
+
deployUrl,
|
|
32
|
+
crossOrigin,
|
|
33
|
+
sri,
|
|
34
|
+
entrypoints: (0, package_chunk_sort_1.generateEntryPoints)({ scripts, styles }),
|
|
35
|
+
files: this.filterAndMapBuildFiles(files, ['.js', '.css']),
|
|
36
|
+
moduleFiles: this.filterAndMapBuildFiles(moduleFiles, ['.js']),
|
|
37
|
+
loadOutputFile: (filePath) => compilation.assets[filePath].source().toString(),
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
getEmittedFiles(compilation) {
|
|
43
|
+
const files = [];
|
|
44
|
+
// adds all chunks to the list of emitted files such as lazy loaded modules
|
|
45
|
+
for (const chunk of compilation.chunks) {
|
|
46
|
+
for (const file of chunk.files) {
|
|
47
|
+
files.push({
|
|
48
|
+
// The id is guaranteed to exist at this point in the compilation process
|
|
49
|
+
id: chunk.id.toString(),
|
|
50
|
+
name: chunk.name,
|
|
51
|
+
file,
|
|
52
|
+
extension: (0, path_1.extname)(file),
|
|
53
|
+
initial: chunk.isOnlyInitial(),
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// other all files
|
|
58
|
+
for (const file of Object.keys(compilation.assets)) {
|
|
59
|
+
files.push({
|
|
60
|
+
file,
|
|
61
|
+
extension: (0, path_1.extname)(file),
|
|
62
|
+
initial: false,
|
|
63
|
+
asset: true,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
// dedupe
|
|
67
|
+
return files.filter(({ file, name }, index) => files.findIndex((f) => f.file === file && (!name || name === f.name)) === index);
|
|
68
|
+
}
|
|
69
|
+
stripBom(data) {
|
|
70
|
+
return data.replace(/^\uFEFF/, '');
|
|
71
|
+
}
|
|
72
|
+
augmentIndexHtml(params) {
|
|
73
|
+
const { loadOutputFile, files, moduleFiles = [], entrypoints } = params;
|
|
74
|
+
let { crossOrigin = 'none' } = params;
|
|
75
|
+
if (params.sri && crossOrigin === 'none') {
|
|
76
|
+
crossOrigin = 'anonymous';
|
|
77
|
+
}
|
|
78
|
+
const stylesheets = new Set();
|
|
79
|
+
const scripts = new Set();
|
|
80
|
+
// Sort files in the order we want to insert them by entrypoint and dedupes duplicates
|
|
81
|
+
const mergedFiles = [...moduleFiles, ...files];
|
|
82
|
+
for (const entrypoint of entrypoints) {
|
|
83
|
+
for (const { extension, file, name } of mergedFiles) {
|
|
84
|
+
if (name !== entrypoint) {
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
switch (extension) {
|
|
88
|
+
case '.js':
|
|
89
|
+
scripts.add(file);
|
|
90
|
+
break;
|
|
91
|
+
case '.css':
|
|
92
|
+
stylesheets.add(file);
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// Find the head and body elements
|
|
98
|
+
const treeAdapter = parse5.treeAdapters.default;
|
|
99
|
+
const document = parse5.parse(params.inputContent, {
|
|
100
|
+
treeAdapter,
|
|
101
|
+
locationInfo: true,
|
|
102
|
+
});
|
|
103
|
+
let headElement;
|
|
104
|
+
let bodyElement;
|
|
105
|
+
for (const docChild of document.childNodes) {
|
|
106
|
+
if (docChild.tagName === 'html') {
|
|
107
|
+
for (const htmlChild of docChild.childNodes) {
|
|
108
|
+
if (htmlChild.tagName === 'head') {
|
|
109
|
+
headElement = htmlChild;
|
|
110
|
+
}
|
|
111
|
+
else if (htmlChild.tagName === 'body') {
|
|
112
|
+
bodyElement = htmlChild;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
if (!headElement || !bodyElement) {
|
|
118
|
+
throw new Error('Missing head and/or body elements');
|
|
119
|
+
}
|
|
120
|
+
// Determine script insertion point
|
|
121
|
+
let scriptInsertionPoint;
|
|
122
|
+
if (bodyElement.__location && bodyElement.__location.endTag) {
|
|
123
|
+
scriptInsertionPoint = bodyElement.__location.endTag.startOffset;
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
// Less accurate fallback
|
|
127
|
+
// parse5 4.x does not provide locations if malformed html is present
|
|
128
|
+
scriptInsertionPoint = params.inputContent.indexOf('</body>');
|
|
129
|
+
}
|
|
130
|
+
let styleInsertionPoint;
|
|
131
|
+
if (headElement.__location && headElement.__location.endTag) {
|
|
132
|
+
styleInsertionPoint = headElement.__location.endTag.startOffset;
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
// Less accurate fallback
|
|
136
|
+
// parse5 4.x does not provide locations if malformed html is present
|
|
137
|
+
styleInsertionPoint = params.inputContent.indexOf('</head>');
|
|
138
|
+
}
|
|
139
|
+
// Inject into the html
|
|
140
|
+
const indexSource = new webpack.sources.ReplaceSource(new webpack.sources.RawSource(params.inputContent, false), params.input);
|
|
141
|
+
let scriptElements = '';
|
|
142
|
+
for (const script of scripts) {
|
|
143
|
+
const attrs = [
|
|
144
|
+
{ name: 'src', value: (params.deployUrl || '') + script },
|
|
145
|
+
];
|
|
146
|
+
if (crossOrigin !== 'none') {
|
|
147
|
+
attrs.push({ name: 'crossorigin', value: crossOrigin });
|
|
148
|
+
}
|
|
149
|
+
// We want to include nomodule or module when a file is not common amongs all
|
|
150
|
+
// such as runtime.js
|
|
151
|
+
const scriptPredictor = ({ file, }) => file === script;
|
|
152
|
+
if (!files.some(scriptPredictor)) {
|
|
153
|
+
// in some cases for differential loading file with the same name is avialable in both
|
|
154
|
+
// nomodule and module such as scripts.js
|
|
155
|
+
// we shall not add these attributes if that's the case
|
|
156
|
+
const isModuleType = moduleFiles.some(scriptPredictor);
|
|
157
|
+
if (isModuleType) {
|
|
158
|
+
attrs.push({ name: 'type', value: 'module' });
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
attrs.push({ name: 'defer', value: null });
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
attrs.push({ name: 'type', value: 'module' });
|
|
166
|
+
}
|
|
167
|
+
if (params.sri) {
|
|
168
|
+
const content = loadOutputFile(script);
|
|
169
|
+
attrs.push(...this.generateSriAttributes(content));
|
|
170
|
+
}
|
|
171
|
+
const attributes = attrs
|
|
172
|
+
.map((attr) => attr.value === null ? attr.name : `${attr.name}="${attr.value}"`)
|
|
173
|
+
.join(' ');
|
|
174
|
+
scriptElements += `<script ${attributes}></script>`;
|
|
175
|
+
}
|
|
176
|
+
indexSource.insert(scriptInsertionPoint, scriptElements);
|
|
177
|
+
// Adjust base href if specified
|
|
178
|
+
if (typeof params.baseHref == 'string') {
|
|
179
|
+
let baseElement;
|
|
180
|
+
for (const headChild of headElement.childNodes) {
|
|
181
|
+
if (headChild.tagName === 'base') {
|
|
182
|
+
baseElement = headChild;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
const baseFragment = treeAdapter.createDocumentFragment();
|
|
186
|
+
if (!baseElement) {
|
|
187
|
+
baseElement = treeAdapter.createElement('base', undefined, [
|
|
188
|
+
{ name: 'href', value: params.baseHref },
|
|
189
|
+
]);
|
|
190
|
+
treeAdapter.appendChild(baseFragment, baseElement);
|
|
191
|
+
indexSource.insert(headElement.__location.startTag.endOffset, parse5.serialize(baseFragment, { treeAdapter }));
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
let hrefAttribute;
|
|
195
|
+
for (const attribute of baseElement.attrs) {
|
|
196
|
+
if (attribute.name === 'href') {
|
|
197
|
+
hrefAttribute = attribute;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
if (hrefAttribute) {
|
|
201
|
+
hrefAttribute.value = params.baseHref;
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
baseElement.attrs.push({ name: 'href', value: params.baseHref });
|
|
205
|
+
}
|
|
206
|
+
treeAdapter.appendChild(baseFragment, baseElement);
|
|
207
|
+
indexSource.replace(baseElement.__location.startOffset, baseElement.__location.endOffset, parse5.serialize(baseFragment, { treeAdapter }));
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
const styleElements = treeAdapter.createDocumentFragment();
|
|
211
|
+
for (const stylesheet of stylesheets) {
|
|
212
|
+
const attrs = [
|
|
213
|
+
{ name: 'rel', value: 'stylesheet' },
|
|
214
|
+
{ name: 'href', value: (params.deployUrl || '') + stylesheet },
|
|
215
|
+
];
|
|
216
|
+
if (crossOrigin !== 'none') {
|
|
217
|
+
attrs.push({ name: 'crossorigin', value: crossOrigin });
|
|
218
|
+
}
|
|
219
|
+
if (params.sri) {
|
|
220
|
+
const content = loadOutputFile(stylesheet);
|
|
221
|
+
attrs.push(...this.generateSriAttributes(content));
|
|
222
|
+
}
|
|
223
|
+
const element = treeAdapter.createElement('link', undefined, attrs);
|
|
224
|
+
treeAdapter.appendChild(styleElements, element);
|
|
225
|
+
}
|
|
226
|
+
indexSource.insert(styleInsertionPoint, parse5.serialize(styleElements, { treeAdapter }));
|
|
227
|
+
return indexSource;
|
|
228
|
+
}
|
|
229
|
+
generateSriAttributes(content) {
|
|
230
|
+
const algo = 'sha384';
|
|
231
|
+
const hash = (0, crypto_1.createHash)(algo).update(content, 'utf8').digest('base64');
|
|
232
|
+
return [{ name: 'integrity', value: `${algo}-${hash}` }];
|
|
233
|
+
}
|
|
234
|
+
filterAndMapBuildFiles(files, extensionFilter) {
|
|
235
|
+
const filteredFiles = [];
|
|
236
|
+
// This test excludes files generated by HMR (e.g. main.hot-update.js).
|
|
237
|
+
const hotUpdateAsset = /hot-update\.[cm]?js$/;
|
|
238
|
+
for (const { file, name, extension, initial } of files) {
|
|
239
|
+
if (name &&
|
|
240
|
+
initial &&
|
|
241
|
+
extensionFilter.includes(extension) &&
|
|
242
|
+
!hotUpdateAsset.test(file)) {
|
|
243
|
+
filteredFiles.push({ file, extension, name });
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
return filteredFiles;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
exports.WriteIndexHtmlPlugin = WriteIndexHtmlPlugin;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { ExecutorContext } from '@nx/devkit';
|
|
2
|
+
import { Configuration } from 'webpack';
|
|
3
|
+
import { NormalizedWebpackExecutorOptions } from '../executors/webpack/schema';
|
|
4
|
+
export declare const nxWebpackComposablePlugin = "nxWebpackComposablePlugin";
|
|
5
|
+
export declare function isNxWebpackComposablePlugin(a: unknown): a is AsyncNxComposableWebpackPlugin;
|
|
6
|
+
export interface NxWebpackExecutionContext {
|
|
7
|
+
options: NormalizedWebpackExecutorOptions;
|
|
8
|
+
context: ExecutorContext;
|
|
9
|
+
configuration?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface NxComposableWebpackPlugin {
|
|
12
|
+
(config: Configuration, ctx: NxWebpackExecutionContext): Configuration;
|
|
13
|
+
}
|
|
14
|
+
export interface AsyncNxComposableWebpackPlugin {
|
|
15
|
+
(config: Configuration, ctx: NxWebpackExecutionContext): Configuration | Promise<Configuration>;
|
|
16
|
+
}
|
|
17
|
+
export declare function composePlugins(...plugins: (NxComposableWebpackPlugin | AsyncNxComposableWebpackPlugin | Promise<NxComposableWebpackPlugin | AsyncNxComposableWebpackPlugin>)[]): ((config: Configuration, ctx: NxWebpackExecutionContext) => Promise<Configuration>) & {
|
|
18
|
+
nxWebpackComposablePlugin: boolean;
|
|
19
|
+
};
|
|
20
|
+
export declare function composePluginsSync(...plugins: NxComposableWebpackPlugin[]): ((config: Configuration, ctx: NxWebpackExecutionContext) => Configuration) & {
|
|
21
|
+
nxWebpackComposablePlugin: boolean;
|
|
22
|
+
};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.composePluginsSync = exports.composePlugins = exports.isNxWebpackComposablePlugin = exports.nxWebpackComposablePlugin = void 0;
|
|
4
|
+
const devkit_1 = require("@nx/devkit");
|
|
5
|
+
exports.nxWebpackComposablePlugin = 'nxWebpackComposablePlugin';
|
|
6
|
+
function isNxWebpackComposablePlugin(a) {
|
|
7
|
+
return a?.[exports.nxWebpackComposablePlugin] === true;
|
|
8
|
+
}
|
|
9
|
+
exports.isNxWebpackComposablePlugin = isNxWebpackComposablePlugin;
|
|
10
|
+
function composePlugins(...plugins) {
|
|
11
|
+
return Object.assign(async function combined(config, ctx) {
|
|
12
|
+
// Webpack may be calling us as a standard config function.
|
|
13
|
+
// Build up Nx context from environment variables.
|
|
14
|
+
// This is to enable `@nx/webpack/plugin` to work with existing projects.
|
|
15
|
+
if (ctx['env']) {
|
|
16
|
+
ensureNxWebpackExecutionContext(ctx);
|
|
17
|
+
// Build this from scratch since what webpack passes us is the env, not config,
|
|
18
|
+
// and `withNX()` creates a new config object anyway.
|
|
19
|
+
config = {};
|
|
20
|
+
}
|
|
21
|
+
for (const plugin of plugins) {
|
|
22
|
+
const fn = await plugin;
|
|
23
|
+
config = await fn(config, ctx);
|
|
24
|
+
}
|
|
25
|
+
return config;
|
|
26
|
+
}, {
|
|
27
|
+
[exports.nxWebpackComposablePlugin]: true,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
exports.composePlugins = composePlugins;
|
|
31
|
+
function composePluginsSync(...plugins) {
|
|
32
|
+
return Object.assign(function combined(config, ctx) {
|
|
33
|
+
for (const plugin of plugins) {
|
|
34
|
+
config = plugin(config, ctx);
|
|
35
|
+
}
|
|
36
|
+
return config;
|
|
37
|
+
}, {
|
|
38
|
+
[exports.nxWebpackComposablePlugin]: true,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
exports.composePluginsSync = composePluginsSync;
|
|
42
|
+
function ensureNxWebpackExecutionContext(ctx) {
|
|
43
|
+
const projectName = process.env.NX_TASK_TARGET_PROJECT;
|
|
44
|
+
const targetName = process.env.NX_TASK_TARGET_TARGET;
|
|
45
|
+
const configurationName = process.env.NX_TASK_TARGET_CONFIGURATION;
|
|
46
|
+
const projectGraph = (0, devkit_1.readCachedProjectGraph)();
|
|
47
|
+
const projectNode = projectGraph.nodes[projectName];
|
|
48
|
+
ctx.options ??= {
|
|
49
|
+
root: devkit_1.workspaceRoot,
|
|
50
|
+
projectRoot: projectNode.data.root,
|
|
51
|
+
sourceRoot: projectNode.data.sourceRoot ?? projectNode.data.root,
|
|
52
|
+
// These aren't actually needed since NxWebpackPlugin and withNx both support them being undefined.
|
|
53
|
+
assets: undefined,
|
|
54
|
+
outputPath: undefined,
|
|
55
|
+
tsConfig: undefined,
|
|
56
|
+
outputFileName: undefined,
|
|
57
|
+
};
|
|
58
|
+
ctx.context ??= {
|
|
59
|
+
projectName,
|
|
60
|
+
targetName,
|
|
61
|
+
configurationName,
|
|
62
|
+
cwd: process.cwd(),
|
|
63
|
+
root: devkit_1.workspaceRoot,
|
|
64
|
+
isVerbose: process.env['NX_VERBOSE_LOGGING'] === 'true',
|
|
65
|
+
};
|
|
66
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createCopyPlugin = void 0;
|
|
4
|
+
const CopyWebpackPlugin = require("copy-webpack-plugin");
|
|
5
|
+
function createCopyPlugin(assets) {
|
|
6
|
+
return new CopyWebpackPlugin({
|
|
7
|
+
patterns: assets.map((asset) => {
|
|
8
|
+
return {
|
|
9
|
+
context: asset.input,
|
|
10
|
+
// Now we remove starting slash to make Webpack place it from the output root.
|
|
11
|
+
to: asset.output,
|
|
12
|
+
from: asset.glob,
|
|
13
|
+
globOptions: {
|
|
14
|
+
ignore: [
|
|
15
|
+
'.gitkeep',
|
|
16
|
+
'**/.DS_Store',
|
|
17
|
+
'**/Thumbs.db',
|
|
18
|
+
...(asset.ignore ?? []),
|
|
19
|
+
],
|
|
20
|
+
dot: true,
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
}),
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
exports.createCopyPlugin = createCopyPlugin;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type GeneratorCallback, type Tree } from '@nx/devkit';
|
|
2
|
+
export type EnsureDependenciesOptions = {
|
|
3
|
+
compiler?: 'swc' | 'tsc';
|
|
4
|
+
uiFramework?: 'none' | 'react';
|
|
5
|
+
};
|
|
6
|
+
export declare function ensureDependencies(tree: Tree, options: EnsureDependenciesOptions): GeneratorCallback;
|