将 Cesium/Resium 与 npx create-react-app 的构建集成无效

Integrating Cesium/Resium with a build of npx create-react-app is not working

我使用的是 "ejected" 版本的 npx create-react-app,因为我需要添加几个依赖项。这一切都很好,直到我需要添加 Cesium 和 Resium。

我一直在按照这些说明配置 webpack,但我假设 "npx create-react-app" 附带的配置有一些要求略有不同。

https://resium.darwineducation.com/installation2

我也按照说明尝试了 craco-cesium,但它似乎也不起作用 - 我收到了相同的消息。

正如你们大多数人所知,React 的 npx 包附带的 webpack 非常大。所以我认为这就是问题所在。我已将以下内容添加到默认 webpack.config.js

const cesiumSource = "../node_modules/cesium/Source"
const cesiumWorkers = "../Build/Cesium/Workers"

{
...
alias: {
    'react-native': 'react-native-web',
     cesium$: 'cesium/Cesium',
     cesium: 'cesium/Source'
},
...
plugins: [
     new CopyWebpackPlugin([
        {
          from: path.join(cesiumSource, cesiumWorkers),
          to: "Workers",
        },
        {
          from: path.join(cesiumSource, "Assets"),
          to: "Assets",
        },
        {
          from: path.join(cesiumSource, "Widgets"),
          to: "Widgets",
        },
     ]),
      new webpack.DefinePlugin(env.stringified),
      new webpack.DefinePlugin({
        CESIUM_BASE_URL: JSON.stringify("/"),
      }),
]
...
}

我遇到错误:

unable to locate '..\node_modules\cesium\Build\Cesium\Workers' at 'C:\Users\USER\Documents\viper-noms\node_modules\cesium\Build\Cesium\Workers'

unable to locate '..\node_modules\cesium\Source\Assets' at 'C:\Users\USER\Documents\viper-noms\node_modules\cesium\Source\Assets'

unable to locate '..\node_modules\cesium\Source\Widgets' at 'C:\Users\USER\Documents\viper-noms\node_modules\cesium\Source\Widgets'

这让我觉得这个问题与 new webpack.DefinePlugin()

有关

有什么想法吗?我很确定 create-react-app 会更改 publicPath,但我不清楚如何适应它。

我无法对 npx create-react-app 构建进行故障排除。但是我能够手动完成模块的安装并让它工作。对于那些需要这种东西的人,这里是使用 React + Redux + Cesium + TypeScript 进行稳定构建的配置文件。

如果有人对我遇到问题的原因有更深入的了解,请随时插话。如果有人可以指出让 create-react-app 正常工作的方法,我会换个答案。

package.JSON:

{
  "name": "project",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "bundle": "webpack",
    "type-check": "tsc --noEmit",
    "type-check:watch": "npm run type-check -- --watch",
    "start": "webpack-dev-server",
    "test": "eslint .",
    "build": "webpack --mode production"
  },
  "devDependencies": {
    "@babel/core": "7.5.5",
    "@babel/plugin-proposal-class-properties": "7.5.5",
    "@babel/plugin-proposal-object-rest-spread": "7.5.5",
    "@babel/preset-env": "7.5.5",
    "@babel/preset-react": "7.0.0",
    "@babel/preset-typescript": "7.3.3",
    "babel-loader": "8.0.6",
    "copy-webpack-plugin": "^5.0.3",
    "css-loader": "^3.1.0",
    "eslint": "^6.0.1",
    "eslint-plugin-react": "^7.14.3",
    "html-webpack-include-assets-plugin": "^2.0.0",
    "html-webpack-plugin": "^3.2.0",
    "strip-pragma-loader": "^1.0.0",
    "style-loader": "^0.23.1",
    "typescript": "^3.3.3",
    "url-loader": "^2.0.1",
    "webpack": "^4.37.0",
    "webpack-cli": "^3.3.6",
    "webpack-dev-server": "^3.7.2"
  },
  "dependencies": {
    "@types/cesium": "^1.59.0",
    "@types/node": "^12.7.5",
    "@types/react": "^16.9.2",
    "@types/react-dom": "^16.9.0",
    "cesium": "^1.59.0",
    "react": "^16.8.6",
    "react-dom": "^16.8.6",
    "redux": "^4.0.4",
    "resium": "^1.7.0",
    "source-map-loader": "^0.2.4",
    "typescript": "^3.6.3"
  }
}

webpack.config.js

"use strict";

const path = require("path");

const webpack = require("webpack");
const HtmlPlugin = require("html-webpack-plugin");
const CopyPlugin = require("copy-webpack-plugin");

const cesiumSource = "node_modules/cesium/Source";
const cesiumWorkers = "../Build/Cesium/Workers";

module.exports = (env, args) => {
  const prod = args.mode === "production";
  return {
    context: __dirname,
    devServer: {
      hot: true,
      port: 3000,
      open: true,
    },
    devtool: !prod ? void 0 : "eval-source-map",
    entry: ["./src/index.js"],
    output: {
      filename: '[name].js',
      path: path.join(__dirname, "./build"),
      sourcePrefix: "",
    },
    resolve: {
      alias: {
        cesium$: "cesium/Cesium",
        cesium: "cesium/Source"
      },
      extensions: [".ts", ".tsx", ".js", ".jsx"]
    },
    mode: prod ? "production" : "development",
    module: {
      rules: [
        {
          test: /\.(ts|js)x?$/,
          exclude: /node_modules/,
          loader: 'babel-loader',
        },
        {
          test: /\.css$/,
          use: ["style-loader", "css-loader"],
        },
        {
          test: /\.(png|gif|jpg|jpeg|svg|xml|json)$/,
          use: ["url-loader"],
        },
        { 
          enforce: "pre", 
          test: /\.js$/, 
          loader: "source-map-loader" 
        },
        ...[
          prod
            ? {
                // Strip cesium pragmas
                test: /\.js$/,
                enforce: "pre",
                include: path.resolve(__dirname, cesiumSource),
                use: [
                  {
                    loader: "strip-pragma-loader",
                    options: {
                      pragmas: {
                        debug: false,
                      },
                    },
                  },
                ],
              }
            : {},
        ],
      ],
    },
    amd: {
      toUrlUndefined: true,
    },
    node: {
      fs: "empty",
    },
    plugins: [
      new webpack.DefinePlugin({
        CESIUM_BASE_URL: JSON.stringify("/"),
      }),
      new CopyPlugin([
        {
          from: path.join(cesiumSource, cesiumWorkers),
          to: "Workers",
        },
        {
          from: path.join(cesiumSource, "Assets"),
          to: "Assets",
        },
        {
          from: path.join(cesiumSource, "Widgets"),
          to: "Widgets",
        },
      ]),
      new HtmlPlugin({ inject: true, template: path.join(path.resolve(__dirname, ''), 'index.html') }),
      ...(prod ? [] : [new webpack.HotModuleReplacementPlugin()]),
    ],
  };
};

tsconfig.json

{
  "compilerOptions": {
    "allowSyntheticDefaultImports": true,
    "noFallthroughCasesInSwitch": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "moduleResolution": "node",
    "esModuleInterop": true,
    "noUnusedLocals": true,
    "noImplicitAny": true,
    "target": "es2015",
    "module": "es2015",
    "strict": true,
    "jsx": "react"
  },
  "include": [
    "src/**/*"
  ],
  "exclude": [
    "node_modules",
    "dist"
  ]
}

.babelrc

{
  "presets": [
    "@babel/env",
    "@babel/typescript",
    "@babel/react"
  ],
  "plugins": [
    "@babel/proposal-class-properties",
    "@babel/proposal-object-rest-spread"
  ]
}

https://resium.darwineducation.com/installation1.

上的文档有点过时了

问题出在 HtmlWebpackIncludeAssetsPlugin 中。而不是这个插件,你需要 安装 html-webpack-tags-plugin。之后将其配置写入弹出 webpack.config.js。我的例子:

const HtmlWebpackPlugin = require('html-webpack-plugin');
const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
const HtmlWebpackTagsPlugin = require('html-webpack-tags-plugin');

  plugins: [
  // Generates an `index.html` file with the <script> injected.
  new HtmlWebpackPlugin(
    Object.assign(
      {},
      {
        inject: true,
        template: paths.appHtml,
      },
      isEnvProduction
        ? {
            minify: {
              removeComments: true,
              collapseWhitespace: true,
              removeRedundantAttributes: true,
              useShortDoctype: true,
              removeEmptyAttributes: true,
              removeStyleLinkTypeAttributes: true,
              keepClosingSlash: true,
              minifyJS: true,
              minifyCSS: true,
              minifyURLs: true,
            },
          }
        : undefined
    )
  ),
  new InterpolateHtmlPlugin(HtmlWebpackPlugin, env.raw),
  new HtmlWebpackTagsPlugin({ tags: ['cesium/Cesium.js', 'cesium/Widgets/widgets.css'], append: false }),
// Other plugins...
].filter(Boolean),