create-react-app更改build/static前缀
最近使用create-react-app创建了一个工程,但是由于后端的/static路由被占用了,需要更改/static文件夹名称,因此有了本次实践
失败尝试
本想着可以用较少的配置代码改动来完成文件夹修改,结果尝试了几个都不行
- 一开始想打算直接mv命令,但是一看到代码中html嵌入的静态资源文件都是带上
/static/xxx
,mv是不行的。 - 网上说可以改
package.json
中homepage
,结果构建出来的文件只是在static文件夹中多了一个web而已,结果如下图所示
- 想了一下是否可以改
PUBLIC_URL
这个env
,发现和尝试2一样,只是在静态资源文件夹前加了个web。
eject代码,分析问题
想到了eject代码,首先找了个新的cra工程,运行eject命令,找到webpack配置。
从下面代码可以看出,cra对这个输出目录名称应该是写死的,就是叫static/xxx
output: {
filename: isEnvProduction
? 'static/js/[name].[contenthash:8].js'
: isEnvDevelopment && 'static/js/bundle.js',
// TODO: remove this when upgrading to webpack 5
futureEmitAssets: true,
// There are also additional JS chunk files if you use code splitting.
chunkFilename: isEnvProduction
? 'static/js/[name].[contenthash:8].chunk.js'
: isEnvDevelopment && 'static/js/[name].chunk.js',
....
},
module: {
strictExportPresence: true,
rules: [
{
// "oneOf" will traverse all following loaders until one will
// match the requirements. When no loader matches it will fall
// back to the "file" loader at the end of the loader list.
oneOf: [
// TODO: Merge this config once `image/avif` is in the mime-db
// https://github.com/jshttp/mime-db
{
test: [/\.avif$/],
loader: require.resolve('url-loader'),
options: {
limit: imageInlineSizeLimit,
mimetype: 'image/avif',
name: 'static/media/[name].[hash:8].[ext]',
},
},
// "url" loader works like "file" loader except that it embeds assets
// smaller than specified limit in bytes as data URLs to avoid requests.
// A missing `test` is equivalent to a match.
{
test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
loader: require.resolve('url-loader'),
options: {
limit: imageInlineSizeLimit,
name: 'static/media/[name].[hash:8].[ext]',
},
},
....
isEnvProduction &&
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: 'static/css/[name].[contenthash:8].css',
chunkFilename: 'static/css/[name].[contenthash:8].chunk.css',
}),
解决问题
本着少改动源码的原则,是不会使用eject命令的。 改动cra的配置,需要使用craco
craco的详情使用可以自行移步到craco
从刚刚eject的代码可以看出,需要改动的地方有三处
- output中的filename和chunkFilename
- mudule.rules中含有options.name的loader
- plugin中的MiniCssExtractPlugin
基于上述3个分析,有了下面的代码。 为了和cra内部一致,使用了craco提供的whenProd函数
module.exports = {
webpack: {
configure: (webpackConfig, { env, paths }) => {
// 更改webpack,资源文件夹位置变更 static -> web
webpackConfig.output = {
...webpackConfig.output,
...{
filename: whenProd(() => 'web/js/[name].[contenthash:8].chunk.js', 'web/js/[name].chunk.js'),
chunkFilename: whenProd(() => 'web/js/[name].[contenthash:8].chunk.js', 'web/js/[name].chunk.js'),
},
}
webpackConfig.plugins = webpackConfig.plugins.map((plugin) => {
whenProd(() => {
if (plugin instanceof MiniCssExtractPlugin) {
Object.assign(plugin.options, {
filename: 'web/css/[name].[contenthash:8].css',
chunkFilename: 'web/css/[name].[contenthash:8].chunk.css',
})
}
})
return plugin
})
webpackConfig.module.rules = webpackConfig.module.rules.map((rule) => {
if (rule.oneOf) {
rule.oneOf = rule.oneOf.map((oneOfRule) => {
if (oneOfRule.options && oneOfRule.options.name) {
oneOfRule.options.name = 'web/media/[name].[hash:8].[ext]';
}
return oneOfRule;
});
}
return rule
})
return webpackConfig;
}
},
};
函数最后必须要return webpackconfig!!
启发网站、资料
转载自:https://juejin.cn/post/7030784682610393119