【问题标题】:Generate single physical javascript file using create-react-app使用 create-react-app 生成单个物理 javascript 文件
【发布时间】:2018-03-06 03:53:04
【问题描述】:

这可能是一个新手问题。 我使用 create-react-app 创建了一个小型 reactjs 应用程序,我看到 bundle.js 文件是从 http://localhost:3000/static/js/bundle.js 提供的。但是,我没有在我的机器上看到物理的“捆绑”javascript 文件。如何生成物理捆绑的 javascript 文件,以便可以在我的 wordpress php 代码中“注册”它?我正在构建一个小型 wordpress 插件,它将在客户端使用 reactjs。 我错过了一些明显的东西吗?

【问题讨论】:

  • npm run build 在您的命令提示符中
  • 当您在开发模式下运行应用程序时,代码由 webpack 从内存中提供。如果您希望生成捆绑包,则应使用命令npm run build。这将生成可以提供服务的捆绑包(已经进行了优化)。
  • 谢谢@sme,@Eduardo Rocha
  • 然而,我得到一个未捕获的 ReferenceError:exports not defined at eval (eval at n.run (browser.min.js:3), :4:23) at Function.n .run (browser.min.js:3) at l (browser.min.js:3) at browser.min.js:3 at XMLHttpRequest.s.onreadystatechange (browser.min.js:3) 错误,在我生成之后捆绑的 javascript 文件并在 wordpress 中注册。我错过了什么?
  • 如果您想使用npm run build 生成一个单个 文件而不是3 个单独的文件,请参阅stackoverflow.com/questions/59331493/…

标签: reactjs create-react-app


【解决方案1】:

正如here 建议的那样,另一种解决方案是使用rewire 包来操作 Create React App 的 webpack 配置,例如

创建一个新文件scripts/build.js

// npm install rewire
const rewire = require('rewire');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const defaults = rewire('react-scripts/scripts/build.js');
const config = defaults.__get__('config');

// Consolidate chunk files instead
config.optimization.splitChunks = {
  cacheGroups: {
    default: false,
  },
};
// Move runtime into bundle instead of separate file
config.optimization.runtimeChunk = false;

// JS
config.output.filename = 'static/js/[name].js';
// CSS remove MiniCssPlugin
config.plugins = config.plugins.filter(plugin =>
    !(plugin instanceof MiniCssExtractPlugin));
// CSS replaces all MiniCssExtractPlugin.loader with style-loader
config.module.rules[2].oneOf = config.module.rules[2].oneOf.map(rule => {
    if (!rule.hasOwnProperty('use')) return rule;
    return Object.assign({}, rule, {
        use: rule.use.map(options => /mini-css-extract-plugin/.test(options.loader)
            ? {loader: require.resolve('style-loader'), options: {}}
            : options)
    });
});

编辑package.json

{
  "scripts": {
    ...
    "build": "npx ./scripts/build.js",
    ...
  }
}

【讨论】:

  • 这适用于创建静态网站,但在应用必须嵌入其他网站时无用。
【解决方案2】:

我遇到了同样的问题,简短的回答是“否”。至少在撰写本文时当前发布的标准“npm run build”是这样。

不过,我将通过帮助您了解正在发生的事情来向您展示如何实现您的目标。首先,你需要意识到 create-react-app 是基于 webpack 模块构建器的:

https://webpack.github.io

因此,执行此操作的规范方法可能是学习 webpack 并为 create-react-app 做出贡献,这样它就可以生成一个或多个您可以删除的 javascript 文件,而不是生成应用程序的静态 index.html 版本进入 Wordpress 页面。我想像“npm run build -js-only”之类的东西。但目前还不可能实现 AFAICT。

好消息是您仍然可以实现将您的 React 应用“注册”到 WP 中的目标,但首先您需要了解一些概念:

1.关于 create-react-app

一个。当您使用 create-react-app 构建应用程序时,它在后台使用 webpack 来执行此操作。它以 create-react-app 定义的预定义方式执行此操作,因此从一开始,您的应用程序就已经构建为 index.html 文件。

b.当您使用“npm start”进行开发时,它实际上是 webpack 从 RAM 为您的应用程序提供服务。

c。当你构建你的应用程序时,实际上是 webpack(以及其他东西)用于创建构建目录。

2。剖析您生成的应用程序

如果您在使用嵌入式 Web 服务器 (npm start) 测试您的应用程序时查看源代码,您会注意到它是一个非常短的 html 文件,具有典型的结构:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <link rel="shortcut icon" href="/favicon.ico">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="theme-color" content="#000000">
    <link rel="manifest" href="/manifest.json">
    <!--
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
    integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
    crossorigin="anonymous">
    -->
    <link rel="stylesheet" href="./bootstrap.min.css">

    <title>React App</title>
  </head>
  <body>
    <noscript>
      You need to enable JavaScript to run this app.
    </noscript>
    <div id="root"></div>
  <script src="/static/js/bundle.js"></script><script src="/static/js/0.chunk.js"></script><script src="/static/js/main.chunk.js"></script></body>
</html>

所以基本上,你有一些头代码来加载清单和样式表。然后你有一个id为“root”的容器,然后你就有了你正在寻找的Javascript文件。

3.在 Worpress 端创建概念验证 HTML 文件

这是您问题的实际答案。正如我上面所说,这可能远非理想,但它确实解决了您遇到的问题。然而,我确实怀疑有一种更简单、更正式的方式来实现这一点,但作为你,我也是 React 和相关技术的新手,所以希望最终会有一些专家最终参与到这个线程中并提出一个更规范的方式。

首先您需要在某个域下为您提供 React 应用程序,假设它在 myreactapp.local 上提供服务。

测试您是否可以通过转到http://myreactapp.local/index.html 来访问您的应用,并且您的应用应该可以像使用“npm start”一样运行。如果出现问题,可能与您的样式表有关。

一旦你的 React 应用程序的静态版本开始工作,只需这样做:

  1. 查看 build/index.html 文件,您会发现 3 个脚本标签。其中一个有实际代码,因此只需复制该代码并在您的 react 应用程序的根目录上创建一个名为 loadme.js 的新脚本(与 index.html 处于同一级别)。

  2. 复制完整的 index.html 文件并在 wordpress 的根目录中创建一个名为 myreactappskel.html 的静态 HTML 文件(仅用于测试 POC)。该文件将作为模板的基础,并将 CSS 和 JS 文件注册到 Wordpress 中;-)

  3. 编辑文件并整齐地格式化它,将所有相对路径替换为 react 应用程序的服务器 URL(例如 myreactapp.local)。

你最终应该得到一个类似这样的文件:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <link rel="shortcut icon" href="http://myreactapp.local/favicon.ico">
    <meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no">
    <meta name="theme-color" content="#000000">
    <link rel="manifest" href="http://myreactapp.local/manifest.json">
    <link rel="stylesheet" href="http://myreactapp.local/bootstrap.min.css">
    <title>My React App POC Static Page in Wordpress</title>
    <link href="http://myreactapp.local/static/css/1.7fbfdb86.chunk.css" rel="stylesheet">
    <link href="http://myreactapp.local/static/css/main.ebeb5bdc.chunk.css" rel="stylesheet">
  </head>

    <title>React App</title>
  </head>
  <body>
    <noscript>
      You need to enable JavaScript to run this app.
    </noscript>
    <div id="someotherid"></div>
    <script src="http://myreactapp.local/loadme.js"></script>
    <script src="http://myreactapp.local/static/js/1.b633dc93.chunk.js"></script>
    <script src="http://myreactapp.local/static/js/main.8958b7bb.chunk.js"></script>

</html>

就是这样!听起来很复杂,但实际上并非如此。请注意一些要点和注意事项:

  1. 将“root”重命名为其他 ID,因为“root”可能会与嵌入它的 HTML 中的某些内容发生冲突。您需要在 index.html 和 index.js 源代码中的 React 源代码中更改此设置。

  2. 请注意脚本在容器 div 之后的情况。这正是打包后的 HTML 的样子。

  3. 注意您在上述步骤中通过获取第一个标签的内容创建的 loadme.js 文件。

  4. 文件的其余部分几乎与生成的文件相同。

与 Wordpress 的其余集成对您来说应该很明显。

希望这会有所帮助。

参考文献

https://facebook.github.io/create-react-app/docs/deployment

https://webpack.github.io

【讨论】:

    【解决方案3】:

    是的,可以通过以下 webpack 配置实现:

    在你的根目录中创建文件 webpack.config.js

    const path = require("path")
    const UglifyJsPlugin = require("uglifyjs-webpack-plugin")
    const glob = require("glob")
    
        module.exports = {
          mode: "production",
          entry: {
            "bundle.js": glob.sync("build/static/?(js|css)/main.*.?(js|css)").map(f => path.resolve(__dirname, f)),
          },
          output: {
            path: path.resolve(__dirname, "build"),
            filename: "static/js/bundle.min.js",
          },
          module: {
            rules: [
              {
                test: /\.css$/,
                use: ["style-loader", "css-loader"],
              },
            ],
          },
          plugins: [new UglifyJsPlugin()],
        }
    

    在 package.json 中

    ...
        "build": "npm run build:react && npm run build:bundle", 
        "build:react": "react-scripts build", 
        "build:bundle": "webpack --config webpack.config.js", 
    ...
    

    来自here的参考

    【讨论】:

    • 除非这是您自己的代码,否则您应该引用源代码,即github.com/facebook/create-react-app/issues/3365
    • 我使用 create-react-app 创建了一个 react 应用程序,然后添加它和一个包含 bundle.min.js 的 html 并运行它——没有任何执行。我在 index.js 的 import 语句之后添加了一个 console.log 语句,在控制台中看不到它。有什么建议吗?
    • 你是否安装了 uglifyjs-webpack-plugin 并创建了 webpack.config.js?甚至有什么错误?
    • 你必须用你的代码单独添加问题:)
    • 修复了示例代码中的几个问题,添加了 modepath 以匹配 react 的默认路径。没有它的渲染目录是“dist”,这可能是你不想要的 react-create-app
    【解决方案4】:

    在意识到 @Niraj 的解决方案不适用于 CRA v4(与 confirmed in this packaged implementation 相同的方法)后,我发现无需弹出即可,只需重新实现相邻 webpack 设置的基本框架(假设reactv17.x 和react-scriptsv4.x):

    1。在项目根目录创建webpack.config.js文件:

    const path = require('path');
    const TerserPlugin = require('terser-webpack-plugin');
    
    module.exports = {
      entry: path.join(__dirname, 'src/index.js'),
      output: {
        path: path.join(__dirname, 'build/static/js'),
        filename: `bundle.min.js`,
      },
      module: {
        rules: [
          {
            test: /\.js/,
            exclude: /node_modules/,
            options: {
              cacheDirectory: true,
              presets: [
                '@babel/preset-env',
                ['@babel/preset-react', { runtime: 'automatic' }],
              ],
            },
            loader: 'babel-loader',
          },
        ],
      },
      optimization: {
        minimize: true,
        minimizer: [new TerserPlugin()],
      },
    };
    

    2。安装依赖项以解析/编译 React 应用程序

    从终端运行:

    npm install --save-dev @babel/preset-env @babel/preset-react babel-loader terser-webpack-plugin webpack-cli
    

    注意使用terser-webpack-plugin 作为UglifyJsPlugin 的后继

    3。将构建 scripts 添加到 package.json

        "build:app": "react-scripts build",
        "build:bundle": "webpack --mode production",
        "build": "npm run build:app && npm run build:bundle",
    

    4。运行构建

    从终端运行npm run build,它应该会生成包含 React 库代码和您的应用程序代码的单个 JS 包,准备好根据需要作为单个 &lt;script&gt; 引用(以及来自标准的分块构建输出) react-scripts 构建)。

    【讨论】:

      【解决方案5】:

      使用react-app-rewiredcustomize-cra 生成包含样式的单个JS 包:

      config-overrides.js

      const { override, adjustStyleLoaders } = require('customize-cra');
      
      module.exports = override(
        (config) => {
          config.optimization.splitChunks = {
            cacheGroups: { default: false }
          };
          config.optimization.runtimeChunk = false;
      
          return config;
        },
        adjustStyleLoaders(({ use }) => {
          use.forEach((loader) => {
            if (/mini-css-extract-plugin/.test(loader.loader)) {
              loader.loader = require.resolve('style-loader');
              loader.options = {};
            }
          });
        })
      );
      

      【讨论】:

        猜你喜欢
        • 2021-10-31
        • 2018-02-01
        • 2019-11-16
        • 1970-01-01
        • 1970-01-01
        • 2021-06-29
        • 2020-06-13
        • 2021-07-13
        • 2020-07-03
        相关资源
        最近更新 更多