我需要帮助我的webpack配置。
目前,我有一个共同的项目,将服务于多个网站。
默认情况下,模板位于这里:jspagesXXX.js
如果在此位置找到覆盖文件:jspagesoverridesSiteNameXXX.js具有相同的js名称,我将使用覆盖文件。
目前,这正在工作。我能够生成所有的入口点与覆盖/默认js (cf下面的代码)。
我不能做的
在dist文件夹内,我想根据网站名称创建一个不同的文件夹架构。这是我想要实现的
dist
- home.js(默认为所有不同的网站)
- site2
-
- home.js
- site5
-
- home.js
代码
module.exports = {
mode: "development",
devtool: "source-map",
entry: {
home: [
XXXsrcmainresourcesstaticjspageshome.js',
],
home_site2: [
XXXsrcmainresourcesstaticjspagesoverridessite2home.js',
],
home_site5: [
XXXsrcmainresourcesstaticjspagesoverridessite5home.js',
]
},
output: {
filename: "[name].js",
path: resolvePath.dist,
publicPath: resolvePath.publicPath
}
}
注意:我可以通过使用规则
在css中执行它任何帮助将是感激的,由于
TLDR;
你可以在这个StackBlitz应用程序中找到一个工作示例。
让我们从配置文件开始:
webpack.config.js
const path = require('path');
// We're doing this import so that we can get autocompletion.
/**
* @type {import("webpack/types").Configuration}
*/
const config = {
entry: {
home: path.join(__dirname, 'src', 'home.js'),
home_site2: path.join(__dirname, 'src/overrides/site2', 'home.js'),
home_site5: path.join(__dirname, 'src/overrides/site5', 'home.js')
},
output: {
path: path.join(__dirname, 'dist'),
filename: fileData => {
const { chunk } = fileData;
if (!chunk.entryModule) {
return crtPath;
}
const { userRequest: req } = chunk.entryModule;
const siteNameDelimiter = 'overrides/';
if (req.includes(siteNameDelimiter)) {
fileData.chunk = null;
fileData.filename = req.slice(
req.indexOf(siteNameDelimiter) + siteNameDelimiter.length
);
return '[path][name].js';
}
return '[name].js';
},
// Emit fresh files every time.
clean: true
},
mode: 'development'
};
module.exports = config;
首先,重要的是要提到entry
对象中的每个项都将导致一个新的块。。这就是为什么在捆绑过程结束时,将有3个文件。让我们来澄清一下什么是块是多少。一个块可以被认为是一组模块。与条目项相关联的块可以称为主块。还有其他类型的块,例如,当您使用
import()
函数时,将创建一个新的块。然而,主块与其他块的区别在于它有webpack注入的代码,也称为运行时代码。这些额外的代码负责惰性加载其他块,处理块的加载等等。其他块也有一些运行时代码,但与主块的数量相比太少了。
在打包过程结束时,块资产创建。通过资产,它意味着块的结果文件,其中还包含所有必要的代码。这部分也是确定块的最终路径的地方。
发生在TemplatedPathPlugin.js
文件中。这里我们还可以看到可用的占位符:
const replacePathVariables = (path, data, assetInfo) => {
/* ... */
// Filename context
//
// Placeholders
//
// for /some/path/file.js?query#fragment:
// [file] - /some/path/file.js
// [query] - ?query
// [fragment] - #fragment
// [base] - file.js
// [path] - /some/path/
// [name] - file
// [ext] - .js
if (typeof data.filename === "string") { /* ... */ }
// Compilation context
/* ... */
// Chunk context
/* ... */
}
就目前情况而言,Filename context
部分是我们感兴趣的部分。
output
选项的配置:
output: {
path: path.join(__dirname, 'dist'),
filename: fileData => {
const { chunk } = fileData;
if (!chunk.entryModule) {
return crtPath;
}
const { userRequest: req } = chunk.entryModule;
const siteNameDelimiter = 'overrides/';
if (req.includes(siteNameDelimiter)) {
fileData.chunk = null;
fileData.filename = req.slice(
req.indexOf(siteNameDelimiter) + siteNameDelimiter.length
);
return '[path][name].js';
}
return '[name].js';
},
// Emit fresh files every time.
clean: true
},
注意output.filename
不再是一个字符串值,而是一个函数。在考虑TemplatedPathPlugin
的逻辑之前立即调用该函数。因此,在初始文件位于overrides
目录下的情况下,生成的块路径将是这样的形式:
/* ... */
// [base] - file.js
// [path] - /some/path/
// [name] - file
/* ... */
const siteNameDelimiter = 'overrides/';
if (req.includes(siteNameDelimiter)) {
fileData.chunk = null;
fileData.filename = req.slice(
req.indexOf(siteNameDelimiter) + siteNameDelimiter.length
);
return '[path][name].js';
}
/* ... *
在本例中,path
是在入口路径中overrides/
之后的内容,而名称是指最后一个/
和.js
之间的内容。
例如,在src/overrides/site2/home.js
,path = site2/
和name = home
中,因此'[path][name].js' = 'site2/home'
.
现在另一个重要的方面:无论返回的路径是什么(例如'home.js'
,'site2/home'
),它将被附加到output.path
的值,在本例中指的是:
path.join(__dirname, 'dist'),
那么,块的最终路径是:
- 家→
dist/home.js
- home_site2→
dist/site2/home.js
- home_site5→
dist/site5/home.js