likes
comments
collection
share

create-react-app更改build/static前缀

作者站长头像
站长
· 阅读数 23

最近使用create-react-app创建了一个工程,但是由于后端的/static路由被占用了,需要更改/static文件夹名称,因此有了本次实践

失败尝试

本想着可以用较少的配置代码改动来完成文件夹修改,结果尝试了几个都不行

  1. 一开始想打算直接mv命令,但是一看到代码中html嵌入的静态资源文件都是带上/static/xxx,mv是不行的。
  2. 网上说可以改package.jsonhomepage,结果构建出来的文件只是在static文件夹中多了一个web而已,结果如下图所示 create-react-app更改build/static前缀

create-react-app更改build/static前缀

  1. 想了一下是否可以改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的代码可以看出,需要改动的地方有三处

  1. output中的filenamechunkFilename
  2. mudule.rules中含有options.name的loader
  3. 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!!

启发网站、资料

blog.actorsfit.com/a?ID=00001-…

转载自:https://juejin.cn/post/7030784682610393119
评论
请登录