我能关闭create-react-app的分块机制吗?

17

我正在使用create-react-app创建React应用项目。

我想知道是否有一种方法可以关闭内置于react脚本中的分块机制。问题是我需要修复构建时创建的捆绑包名称。


为什么你必须修复名称? - Mark
2
我正在开发VS Code扩展程序,需要导入捆绑包。因此,我需要知道它的名称。 - Darko
有人能够使用 react-scripts 5.0.0 做到这一点吗? - Michel Hua
6个回答

16
可以通过使用react-app-rewired扩展您的 CRA 来完成此操作,它允许您修改 webpack 配置。

更改需要移除构建文件名称中的哈希。

  1. 安装 react-app-rewired

npm install react-app-rewired --save-dev

  1. 在根目录(即package.json所在位置)创建config-overrides.js文件。

  2. 将以下代码放入config-overrides.js文件中。它会保留所有 CRA 设置,只是从文件名中删除哈希部分。

    module.exports = function override(config, env) {
        config.output = {
            ...config.output, // 复制所有设置
            filename: "static/js/[name].js",
            chunkFilename: "static/js/[name].chunk.js",
        };
        return config;
    };
  1. 使用新配置。在package.json文件的scripts部分,将"build": "react-scripts build",替换为"build": "react-app-rewired build",

除非您要更改更多配置,否则仅在build中使用react-app-rewired即可。否则,请在其他脚本中除eject之外的所有脚本中替换react-scriptsreact-app-rewired


5
有没有什么办法也改变CSS资产? - Astrit Spanca
1
同样的问题在这里,如何更改CSS资源? - Skatox
1
请参见下面的答案,其中提供了处理 CSS 和媒体文件的建议版本。 - Giraphi

8

如其他人所指出的那样,您可以尝试使用react-app-rewired来替代弹出。这是一个版本,它还处理css和媒体文件:

在安装了npm install react-app-rewired --save-dev之后,我创建了一个config-overrides.js文件,并添加了以下内容:

module.exports = function override(config, env) {
    if (env !== "production") {
        return config;
    }

    // Get rid of hash for js files
    config.output.filename = "static/js/[name].js"
    config.output.chunkFilename = "static/js/[name].chunk.js"

    // Get rid of hash for css files
    const miniCssExtractPlugin = config.plugins.find(element => element.constructor.name === "MiniCssExtractPlugin");
    miniCssExtractPlugin.options.filename = "static/css/[name].css"
    miniCssExtractPlugin.options.chunkFilename = "static/css/[name].css"

    // Get rid of hash for media files
    config.module.rules[1].oneOf.forEach(oneOf => {
        if (!oneOf.options ||  oneOf.options.name !== "static/media/[name].[hash:8].[ext]") {
            return;
        }
        oneOf.options.name = "static/media/[name].[ext]"
    });

    return config;
};

7

我发现你可以通过设置 splitChunks webpack 配置来禁用块划分。 更多详情请参见 https://github.com/facebook/create-react-app/issues/5306#issuecomment-431431877

然而,这不会从包名称中删除contenthash部分,你仍将在名称中拥有该随机字符串。

要删除它,请转到您的webpack.config并编辑捆绑名称

'static/js/[name].[contenthash:8].js' => 'static/js/[name].js'


1
谢谢,你可能拯救了我们在项目中使用嵌入式React应用的能力。对于嵌入React应用程序到iframe中的问题,它非常有效。 - Paweł Hajduk

7
这是Darko答案的扩展和改进版本。我创建它主要是为了节省其他人的时间,他们对this comment中提到的解决方案不完全满意,并且没有耐心挖掘this comment,后者以更好的方式解决了这个问题。
这种“hacky”方法的主要思想是在原始脚本上重新编写标准的react-scriptswebpack配置并注入回去。
为此,您需要从npmjs.org安装rewire软件包,如下所示:
npm install rewire --save-dev

然后您需要创建一个单独的构建脚本,将“包装”原始的react build脚本,并确保它会使用更正的webpack配置。传统的方法是将此文件保存在./scripts文件夹中。因此,让我们称其为./scripts/build.js。它的内容如下:

const rewire = require('rewire');
const path = require('path');

// Pointing to file which we want to re-wire — this is original build script
const defaults = rewire('react-scripts/scripts/build.js');

// Getting configuration from original build script
let config = defaults.__get__('config');

// If we want to move build result into a different folder, we can do that!
// Please note: that should be an absolute path!
config.output.path = path.join(path.dirname(__dirname), 'custom/target/folder');

// If we want to rename resulting bundle file to not have hashes, we can do that!
config.output.filename = 'custom-bundle-name.js';

// And the last thing: disabling splitting
config.optimization.splitChunks = {
    cacheGroups: {
        default: false,
    },
};
config.optimization.runtimeChunk = false;

接下来,我们应该在 packages.json 中使用这个构建脚本,而不是标准的构建脚本,像这样:

...
  "scripts": {
    "start": "react-scripts start",
    "build": "node ./scripts/build.js",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
...

4

有一种无需执行 eject 命令的 hack:

  1. yarn add --dev rewire

  2. create file in root and name it build-non-split.js

  3. fill inside it by below codes:

    const rewire = require('rewire');
    const defaults = rewire('react-scripts/scripts/build.js');
    let config = defaults.__get__('config');
    
    config.optimization.splitChunks = {
        cacheGroups: {
            default: false,
        },
    };
    
    config.optimization.runtimeChunk = false;
    
  4. change the build script inside your package.json to:

    "build": "node ./scripts/build-non-split.js",
    
  5. yarn build


可能的解决方案来源:https://github.com/facebook/create-react-app/issues/5306#issuecomment-433425838 - TomTasche
如何使其也适用于CSS文件? - Michel Hua
@MichelHua,我使用了css-in-js,如果你想使用其他CSS方法也可以,你应该将CSS作为css-modules导入,例如:import styles from './styles.css'; 然后在使用时必须这样使用:<Comp className={styles.container}> - AmerllicA

3

我不知道如何关闭分块,但你可以尝试实现你的目标。

更新到最新的React和React-DOM,运行“yarn react@next react-dom@next”(或npm命令执行相同操作)

现在你应该有了最新的React版本,因此你可以使用React.lazy/React.Suspense进行代码拆分,使用钩子等。

现在你可以使用(以下是组件或依赖项示例)来命名你的块。

 const MyComp = lazy(() =>   import(/* webpackChunkName: 'MyChunkNmame'
*/ './MyComp'), );

const myLib= await import(/* webpackChunkName: "myLib" */ 'myLib');

如果在使用import语法时遇到错误,您需要使用babel-plugin-syntax-dynamic-import插件。将"babel"字段放入您的包json中。

现在,您可以命名代码块并实现最新的代码拆分方式——希望这有所帮助。这里是React.lazy React.Suspense的链接-https://reactjs.org/blog/2018/10/23/react-v-16-6.html


这不是我要找的,但还是谢谢你。在某些情况下,为块命名确实很方便。我实际上发现了一些类似问题的 GitHub 讨论。我会尽快写出答案。 - Darko

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接