使用 create-react-app 生成单个物理 javascript 文件

IT技术 reactjs create-react-app
2021-05-20 08:39:15

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

4个回答

另一种解决方案,如建议在这里,是使用再布线封装操纵创建应用程序做出react的的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",
    ...
  }
}

我有同样的问题,简短的回答是 NO至少在撰写本文时,目前已发布的标准“npm run build”是这样的。

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

https://webpack.github.io

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

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

1.关于create-react-app

一个。当你使用 create-react-app 搭建你的应用程序时,它在幕后使用 webpack 来做到这一点。它以 create-react-app 定义的预定义方式执行此操作,因此从一开始,您的应用程序就已经构建为可作为 index.html 文件提供服务。

当您使用“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”可能会与嵌入此 ID 的 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

是的,可以通过以下 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", 
...

这里参考

在意识到@Niraj 的解决方案不适用于 CRA v4(如相同方法的打包实现确认的)后,我发现无需弹出即可,只需重新实现相邻webpack设置的react基本框架(假设v17.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.添加构建scriptspackage.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 包,准备好<script>根据需要作为单个引用放入(以及标准react-scripts构建的分块构建输出)。