Skip to content

Commit 0128046

Browse files
webpack configurations
1 parent 11a20b9 commit 0128046

File tree

3 files changed

+231
-143
lines changed

3 files changed

+231
-143
lines changed
Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
const path = require('path')
2+
3+
class JSEntryWebpackPlugin {
4+
constructor(options = {}) {
5+
this.options = {
6+
filename: 'index.js',
7+
template: 'auto',
8+
publicPath: options.publicPath === undefined ? 'auto' : options.publicPath,
9+
...options,
10+
}
11+
}
12+
13+
apply(compiler) {
14+
compiler.hooks.emit.tap('InjectCssEntry', compilation => {
15+
// console.log(Object.keys(compilation.assets))
16+
17+
/** output filenames for the given entry names */
18+
const entryNames = Object.keys(compiler.options.entry)
19+
const outputFileNames = new Set(
20+
(entryNames.length ? entryNames : ['main']).map(entryName =>
21+
// Replace '[name]' with entry name
22+
this.options.filename.replace(/\[name\]/g, entryName),
23+
),
24+
)
25+
26+
/** Option for every entry point */
27+
const entryOption = Array.from(outputFileNames).map(filename => ({
28+
...this.options,
29+
filename,
30+
}))[0]
31+
32+
/** The public path used inside the html file */
33+
const publicPath = this.getPublicPath(
34+
compilation,
35+
entryOption.filename,
36+
entryOption.publicPath,
37+
)
38+
39+
/** build output path */
40+
const templatePath = this.getTemplatePath(entryOption.template, compilation.options)
41+
42+
/** Generated file paths from the entry point names */
43+
const assets = this.htmlWebpackPluginAssets(
44+
compilation,
45+
// 只处理一个
46+
Array.from(compilation.entrypoints.keys()).slice(0, 1),
47+
publicPath,
48+
templatePath,
49+
)
50+
51+
// js entry
52+
if (!compilation.assets[assets.entry]) return
53+
54+
let content = `(function() {
55+
// const scripts = [];
56+
let scripts = ${JSON.stringify(assets.js)};
57+
for (let i = 0; i < scripts.length; i++) {
58+
const scriptEle = document.createElement('script');
59+
scriptEle.src = scripts[i];
60+
// scripts.push(scriptEle);
61+
document.body.appendChild(scriptEle);
62+
}
63+
})()`;
64+
65+
compilation.assets[entryOption.filename] = {
66+
source() {
67+
return content
68+
},
69+
size() {
70+
return content.length
71+
},
72+
}
73+
})
74+
}
75+
76+
htmlWebpackPluginAssets(compilation, entryNames, publicPath, templatePath) {
77+
// https://github.com/jantimon/html-webpack-plugin/blob/main/index.js#L640
78+
const assets = {
79+
publicPath,
80+
templatePath,
81+
entry: '',
82+
js: [],
83+
css: [],
84+
}
85+
86+
// Extract paths to .js, .mjs and .css files from the current compilation
87+
const entryPointPublicPathMap = {}
88+
const extensionRegexp = /\.(css|js)(\?|$)/
89+
for (let i = 0; i < entryNames.length; i++) {
90+
const entryName = entryNames[i]
91+
/** entryPointUnfilteredFiles - also includes hot module update files */
92+
const entryPointUnfilteredFiles = compilation.entrypoints.get(entryName).getFiles()
93+
94+
const entryPointFiles = entryPointUnfilteredFiles.filter(chunkFile => {
95+
// compilation.getAsset was introduced in webpack 4.4.0
96+
// once the support pre webpack 4.4.0 is dropped please
97+
// remove the following guard:
98+
const asset = compilation.getAsset && compilation.getAsset(chunkFile)
99+
if (!asset) {
100+
return true
101+
}
102+
// Prevent hot-module files from being included:
103+
const assetMetaInformation = asset.info || {}
104+
return !(assetMetaInformation.hotModuleReplacement || assetMetaInformation.development)
105+
})
106+
107+
// Prepend the publicPath and append the hash depending on the
108+
// webpack.output.publicPath and hashOptions
109+
// E.g. bundle.js -> /bundle.js?hash
110+
const entryPointPublicPaths = entryPointFiles.map(chunkFile => {
111+
const urlPath = this.urlencodePath(chunkFile)
112+
const entryPointPublicPath = publicPath + urlPath
113+
114+
if (chunkFile.endsWith('.js')) {
115+
assets.entry = urlPath
116+
}
117+
return entryPointPublicPath
118+
})
119+
120+
entryPointPublicPaths.forEach(entryPointPublicPath => {
121+
const extMatch = extensionRegexp.exec(entryPointPublicPath)
122+
// Skip if the public path is not a .css, .mjs or .js file
123+
if (!extMatch) {
124+
return
125+
}
126+
// Skip if this file is already known
127+
// (e.g. because of common chunk optimizations)
128+
if (entryPointPublicPathMap[entryPointPublicPath]) {
129+
return
130+
}
131+
entryPointPublicPathMap[entryPointPublicPath] = true
132+
const ext = extMatch[1]
133+
assets[ext].push(entryPointPublicPath)
134+
})
135+
}
136+
return assets
137+
}
138+
139+
getPublicPath(compilation, outputName, customPublicPath) {
140+
const compilationHash = compilation.hash
141+
142+
/**
143+
* @type {string} the configured public path to the asset root
144+
* if a path publicPath is set in the current webpack config use it otherwise
145+
* fallback to a relative path
146+
*/
147+
const webpackPublicPath = compilation.getAssetPath(compilation.outputOptions.publicPath, {
148+
hash: compilationHash,
149+
})
150+
151+
// Webpack 5 introduced "auto" as default value
152+
const isPublicPathDefined = webpackPublicPath !== 'auto'
153+
154+
let publicPath =
155+
// If the html-webpack-plugin options contain a custom public path uset it
156+
customPublicPath !== 'auto'
157+
? customPublicPath
158+
: isPublicPathDefined
159+
? // If a hard coded public path exists use it
160+
webpackPublicPath
161+
: // If no public path was set get a relative url path
162+
path
163+
.relative(
164+
path.resolve(compilation.options.output.path, path.dirname(outputName)),
165+
compilation.options.output.path,
166+
)
167+
.split(path.sep)
168+
.join('/')
169+
170+
if (publicPath.length && publicPath.substr(-1, 1) !== '/') {
171+
publicPath += '/'
172+
}
173+
174+
return publicPath
175+
}
176+
177+
getTemplatePath(template, options) {
178+
const { context, output } = options
179+
180+
return template === 'auto'
181+
? path.join(output.path, path.sep)
182+
: path.join(context || '', template)
183+
}
184+
185+
urlencodePath(filePath) {
186+
// some+path/demo.html?value=abc?def
187+
const queryStringStart = filePath.indexOf('?')
188+
const urlPath = queryStringStart === -1 ? filePath : filePath.substr(0, queryStringStart)
189+
const queryString = filePath.substr(urlPath.length)
190+
// Encode all parts except '/' which are not part of the querystring:
191+
const encodedUrlPath = urlPath.split('/').map(encodeURIComponent).join('/')
192+
return encodedUrlPath + queryString
193+
}
194+
}
195+
196+
JSEntryWebpackPlugin.version = 1
197+
198+
module.exports = JSEntryWebpackPlugin

client/packages/lowcoder-sdk/webpack.config.cjs

Lines changed: 10 additions & 142 deletions
Original file line numberDiff line numberDiff line change
@@ -1,79 +1,11 @@
11
const path = require("path");
22
const TerserPlugin = require('terser-webpack-plugin');
33
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
4-
// const RemarkHTML = require("remark-html")
54
const webpack = require("webpack");
6-
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin
7-
const { buildVars } = require("./src/dev-utils/buildVars.cjs");
8-
9-
// import path from "path";
10-
// import { fileURLToPath } from 'url';
11-
// import TerserPlugin from "terser-webpack-plugin";
12-
// import TsconfigPathsPlugin from "tsconfig-paths-webpack-plugin";
13-
// // const RemarkHTML = require("remark-html")
14-
// import webpack from "webpack";
15-
16-
// const __filename = fileURLToPath(import.meta.url);
17-
// const __dirname = path.dirname(__filename);
5+
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin;
6+
const JSEntryWebpackPlugin = require('./plugins/JSEntryWebpackPlugin.cjs');
187

19-
// const buildVars = [
20-
// {
21-
// name: "PUBLIC_URL",
22-
// defaultValue: "/",
23-
// },
24-
// {
25-
// name: "REACT_APP_EDITION",
26-
// defaultValue: "community",
27-
// },
28-
// {
29-
// name: "REACT_APP_LANGUAGES",
30-
// defaultValue: "",
31-
// },
32-
// {
33-
// name: "REACT_APP_COMMIT_ID",
34-
// defaultValue: "00000",
35-
// },
36-
// {
37-
// name: "REACT_APP_API_HOST",
38-
// defaultValue: "",
39-
// },
40-
// {
41-
// name: "LOWCODER_NODE_SERVICE_URL",
42-
// defaultValue: "",
43-
// },
44-
// {
45-
// name: "REACT_APP_ENV",
46-
// defaultValue: "production",
47-
// },
48-
// {
49-
// name: "REACT_APP_BUILD_ID",
50-
// defaultValue: "",
51-
// },
52-
// {
53-
// name: "REACT_APP_LOG_LEVEL",
54-
// defaultValue: "error",
55-
// },
56-
// {
57-
// name: "REACT_APP_IMPORT_MAP",
58-
// defaultValue: "{}",
59-
// },
60-
// {
61-
// name: "REACT_APP_SERVER_IPS",
62-
// defaultValue: "",
63-
// },
64-
// {
65-
// name: "REACT_APP_BUNDLE_BUILTIN_PLUGIN",
66-
// defaultValue: "",
67-
// },
68-
// {
69-
// name: "REACT_APP_BUNDLE_TYPE",
70-
// defaultValue: "app",
71-
// },
72-
// {
73-
// name: "REACT_APP_DISABLE_JS_SANDBOX",
74-
// defaultValue: "",
75-
// },
76-
// ];
8+
const { buildVars } = require("./src/dev-utils/buildVars.cjs");
779

7810
const define = {};
7911
buildVars.forEach(({ name, defaultValue }) => {
@@ -83,7 +15,7 @@ buildVars.forEach(({ name, defaultValue }) => {
8315
const apiBaseUrl = "http://localhost:8000";
8416

8517
module.exports = {
86-
stats: 'verbose',
18+
// stats: 'verbose',
8719
mode: 'production',
8820
entry: "./index-bundle.jsx",
8921
externals: {
@@ -165,12 +97,12 @@ module.exports = {
16597
})]
16698
},
16799
output: {
168-
// path: __dirname + "/dist",
169100
path: path.resolve(__dirname, 'bundle'),
170101
// publicPath: "https://sdk.lowcoder.cloud/",
171102
publicPath: "/",
172103
// filename: "bundle.js",
173104
filename: '[name].bundle.js',
105+
clean: true,
174106
},
175107
plugins: [
176108
new webpack.DefinePlugin({
@@ -181,7 +113,11 @@ module.exports = {
181113
new webpack.IgnorePlugin({
182114
resourceRegExp: /.test.(ts|tsx)$/,
183115
}),
184-
new BundleAnalyzerPlugin()
116+
new JSEntryWebpackPlugin({
117+
path: path.resolve(__dirname, 'bundle'),
118+
filename: 'bundle.js'
119+
}),
120+
// new BundleAnalyzerPlugin()
185121
],
186122
optimization: {
187123
minimize: true,
@@ -192,75 +128,7 @@ module.exports = {
192128
splitChunks: {
193129
chunks: 'all',
194130
},
195-
// splitChunks: {
196-
// cacheGroups: {
197-
// vendor: {
198-
// test: /[\\/]node_modules[\\/]/,
199-
// name: 'vendors',
200-
// chunks: 'all',
201-
// },
202-
// },
203-
// },
204-
// splitChunks: {
205-
// chunks: 'all',
206-
// minSize: 10000,
207-
// minRemainingSize: 0,
208-
// minChunks: 1,
209-
// maxAsyncRequests: 30,
210-
// maxInitialRequests: 30,
211-
// enforceSizeThreshold: 50000,
212-
// cacheGroups: {
213-
// default: {
214-
// minChunks: 2,
215-
// priority: -20,
216-
// reuseExistingChunk: true,
217-
// },
218-
// defaultVendors: {
219-
// test: /[\\/]node_modules[\\/]/,
220-
// priority: -10,
221-
// reuseExistingChunk: true,
222-
// // name(module) {
223-
// // // get the name. E.g. node_modules/packageName/not/this/part.js
224-
// // // or node_modules/packageName
225-
// // const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1];
226-
// // // if (packageName === 'antd') {
227-
// // // return 'antd';
228-
// // // }
229-
// // // if (packageName === 'antd-mobile') {
230-
// // // return 'antd-mobile';
231-
// // // }
232-
// // // if (packageName === 'lodash') {
233-
// // // return 'lodash';
234-
// // // }
235-
// // // if (packageName === 'moment') {
236-
// // // return 'moment';
237-
// // // }
238-
// // // if (packageName === 'dayjs') {
239-
// // // return 'dayjs';
240-
// // // }
241-
// // // npm package names are URL-safe, but some servers don't like @ symbols
242-
// // // return `npm.${packageName.replace('@', '')}`;
243-
// // // return `npm.${packageName.replace('@', '')}`;
244-
// // return `vendor`;
245-
// // },
246-
// },
247-
// },
248-
// },
249131
runtimeChunk: 'single',
250-
// splitChunks: {
251-
// chunks: 'all',
252-
// }
253-
// splitChunks: {
254-
// minSize: 0,
255-
// cacheGroups: {
256-
// // reuseExistingChunk: true,
257-
// vendor: {
258-
// test: /[\\/]node_modules[\\/]/,
259-
// name: 'vendors',
260-
// chunks: 'all'
261-
// }
262-
// }
263-
// }
264132
},
265133
devServer: {
266134
static: {

0 commit comments

Comments
 (0)