Webpack:根据条目名称设置我的资产的路径
Webpack: Set the path for my assets according to the entry name
使用 webpack,我有一个可以处理多个条目的多页面应用程序。我有一个这样的项目树:
-- webpack.config.js
-- src/
-- first/
-- main.ts
-- helper.ts
-- main.css
-- index.html
-- second/
-- main.ts
-- main.css
-- index.html
-- assets/
-- myAsset1.png
-- myAsset2.png
-- myAsset3.png
我想要按文件夹整理的东西。为此,我每次都为 name
或 filename
添加 [name]/...
,如下所示:
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const path = require('path');
module.exports = {
entry: {
first: './src/first/main.ts',
second: './src/second/main.ts',
},
output: {
path: path.resolve(__dirname, 'dist'), // output directory
filename: '[name]/script.js', // name of the generated bundle
publicPath: '/',
},
module: {
rules: [
// TypeScript
{
test: /\.ts$/,
loader: 'ts-loader',
options: {
onlyCompileBundledFiles: true,
},
},
// Style
{
test: /\.s?[ac]ss$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
},
{
loader: 'postcss-loader',
options: {
sourceMap: true,
},
},
{
loader: 'resolve-url-loader',
},
{
loader: 'sass-loader',
},
],
},
// Fonts & Images
{
test: /\.(woff(2)?|ttf|eot|jpg|png|svg|md)(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'file-loader',
options: {
limit: 8192,
name: '[name].[ext]',
},
},
],
},
],
},
resolve: {
modules: ['node_modules', path.resolve(process.cwd(), 'src')],
extensions: ['.ts', '.js'],
},
plugins: [
new HtmlWebpackPlugin({
template: path.join(process.cwd(), 'src/first/index.html'),
inject: true,
chunks: ['first'],
filename: 'first/index.html',
}),
new HtmlWebpackPlugin({
template: './src/second/index.html',
inject: true,
chunks: ['second'],
filename: 'second/index.html',
}),
new MiniCssExtractPlugin({
filename: '[name]/style.css',
chunkFilename: '[name]/style.css',
}),
],
};
结果将是:
-- dist/
-- first/
-- script.js
-- style.css
-- index.html
-- second/
-- script.js
-- style.css
-- index.html
-- myAsset1.png
-- myAsset2.png
-- myAsset3.png
但是,我想要文件夹名称中的资产根据导入的条目。实际上,myAssets1.png
和 myAssets2.png
是从 first
文件夹的 main.ts
导入的,myAssets3.png
是从 second
文件夹的 main.ts
导入的
-- dist/
-- first/
-- script.js
-- style.css
-- index.html
-- myAsset1.png
-- myAsset2.png
-- second/
-- script.js
-- style.css
-- index.html
-- myAsset3.png
如何根据条目名称设置资源路径?
为了指定 file-loader 正在处理的资产将保存在您需要的位置,需要做一些事情:
- 您需要确定哪个入口点是该文件的发布者
- 将其作为
resourceQuery
注入
- 在
file-loader
的name
函数中使用注入的resourceQuery
指定路径
为了实现 1,2,您可以创建一个自定义加载器,它将提取发行者并附加查询。
// entry-dir-injector-loader.js
const path = require('path');
function recursiveIssuer(m) {
if (m.issuer && m.issuer.context) {
return recursiveIssuer(m.issuer);
} else if (m.context) {
return m.context;
} else {
return false;
}
}
module.exports = function (content) {
const entry = recursiveIssuer(this._module);
const entryRelativePath = path.relative(this.rootContext, entry).replace('src/', '');
this.resourceQuery = `?entryDir=${entryRelativePath}`;
return content;
};
然后将 name
指定为 函数 ,提取查询。
module.exports = {
module: {
rules: [
{
test: /\.(woff(2)?|ttf|eot|jpg|png|svg|md)(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'file-loader',
options: {
limit: 8192,
name(resourcePath, resourceQuery) {
const entryDir = resourceQuery
.substring(1)
.split('&')
.filter((key) => key.startsWith('entryDir='))
.map((key) => key.split('=').pop())
.join('');
return path.join(entryDir, `[name].[ext]`);
},
},
},
{
loader: './entry-dir-injector-loader.js',
},
],
},
],
},
};
使用 webpack,我有一个可以处理多个条目的多页面应用程序。我有一个这样的项目树:
-- webpack.config.js
-- src/
-- first/
-- main.ts
-- helper.ts
-- main.css
-- index.html
-- second/
-- main.ts
-- main.css
-- index.html
-- assets/
-- myAsset1.png
-- myAsset2.png
-- myAsset3.png
我想要按文件夹整理的东西。为此,我每次都为 name
或 filename
添加 [name]/...
,如下所示:
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const path = require('path');
module.exports = {
entry: {
first: './src/first/main.ts',
second: './src/second/main.ts',
},
output: {
path: path.resolve(__dirname, 'dist'), // output directory
filename: '[name]/script.js', // name of the generated bundle
publicPath: '/',
},
module: {
rules: [
// TypeScript
{
test: /\.ts$/,
loader: 'ts-loader',
options: {
onlyCompileBundledFiles: true,
},
},
// Style
{
test: /\.s?[ac]ss$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
},
{
loader: 'postcss-loader',
options: {
sourceMap: true,
},
},
{
loader: 'resolve-url-loader',
},
{
loader: 'sass-loader',
},
],
},
// Fonts & Images
{
test: /\.(woff(2)?|ttf|eot|jpg|png|svg|md)(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'file-loader',
options: {
limit: 8192,
name: '[name].[ext]',
},
},
],
},
],
},
resolve: {
modules: ['node_modules', path.resolve(process.cwd(), 'src')],
extensions: ['.ts', '.js'],
},
plugins: [
new HtmlWebpackPlugin({
template: path.join(process.cwd(), 'src/first/index.html'),
inject: true,
chunks: ['first'],
filename: 'first/index.html',
}),
new HtmlWebpackPlugin({
template: './src/second/index.html',
inject: true,
chunks: ['second'],
filename: 'second/index.html',
}),
new MiniCssExtractPlugin({
filename: '[name]/style.css',
chunkFilename: '[name]/style.css',
}),
],
};
结果将是:
-- dist/
-- first/
-- script.js
-- style.css
-- index.html
-- second/
-- script.js
-- style.css
-- index.html
-- myAsset1.png
-- myAsset2.png
-- myAsset3.png
但是,我想要文件夹名称中的资产根据导入的条目。实际上,myAssets1.png
和 myAssets2.png
是从 first
文件夹的 main.ts
导入的,myAssets3.png
是从 second
文件夹的 main.ts
导入的
-- dist/
-- first/
-- script.js
-- style.css
-- index.html
-- myAsset1.png
-- myAsset2.png
-- second/
-- script.js
-- style.css
-- index.html
-- myAsset3.png
如何根据条目名称设置资源路径?
为了指定 file-loader 正在处理的资产将保存在您需要的位置,需要做一些事情:
- 您需要确定哪个入口点是该文件的发布者
- 将其作为
resourceQuery
注入
- 在
file-loader
的name
函数中使用注入的resourceQuery
指定路径
为了实现 1,2,您可以创建一个自定义加载器,它将提取发行者并附加查询。
// entry-dir-injector-loader.js
const path = require('path');
function recursiveIssuer(m) {
if (m.issuer && m.issuer.context) {
return recursiveIssuer(m.issuer);
} else if (m.context) {
return m.context;
} else {
return false;
}
}
module.exports = function (content) {
const entry = recursiveIssuer(this._module);
const entryRelativePath = path.relative(this.rootContext, entry).replace('src/', '');
this.resourceQuery = `?entryDir=${entryRelativePath}`;
return content;
};
然后将 name
指定为 函数 ,提取查询。
module.exports = {
module: {
rules: [
{
test: /\.(woff(2)?|ttf|eot|jpg|png|svg|md)(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'file-loader',
options: {
limit: 8192,
name(resourcePath, resourceQuery) {
const entryDir = resourceQuery
.substring(1)
.split('&')
.filter((key) => key.startsWith('entryDir='))
.map((key) => key.split('=').pop())
.join('');
return path.join(entryDir, `[name].[ext]`);
},
},
},
{
loader: './entry-dir-injector-loader.js',
},
],
},
],
},
};