如何修复错误“无法编译:./node_modules/@react-leaflet/core/esm/path.js 10:41 模块解析失败:意外的令牌(10:41)”

87

我正在尝试创建一个使用React-TypeScriptLeaflet的应用程序。我使用了以下命令安装依赖项:

npm install leaflet react-leaflet @types/react @types/leaflet --save

但是当我启动应用程序时,它显示:

    ./node_modules/@react-leaflet/core/esm/path.js 10:41
Module parse failed: Unexpected token (10:41)
File was processed with these loaders:
 * ./node_modules/babel-loader/lib/index.js
You may need an additional loader to handle the result of these loaders.
|   useEffect(function updatePathOptions() {
|     if (props.pathOptions !== optionsRef.current) {
>       const options = props.pathOptions ?? {};
|       element.instance.setStyle(options);
|       optionsRef.current = options;

这是我的package.json文件

{
  "name": "aq-monitor",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^5.12.0",
    "@testing-library/react": "^11.2.7",
    "@testing-library/user-event": "^12.8.3",
    "@types/jest": "^26.0.23",
    "@types/leaflet": "^1.7.0",
    "@types/node": "^12.20.13",
    "@types/react": "^17.0.5",
    "@types/react-dom": "^17.0.5",
    "antd": "^4.15.5",
    "leaflet": "^1.7.1",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "react-leaflet": "^3.2.0",
    "react-router-dom": "^5.2.0",
    "react-scripts": "4.0.3",
    "typescript": "^4.2.4",
    "web-vitals": "^1.1.2"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "devDependencies": {
    "@types/react-router-dom": "^5.1.7"
  }
}

这里是map/index.tsx

import React from 'react';
import './styles.css';
import L, { LatLngExpression } from "leaflet";
import "leaflet/dist/leaflet.css";
import {MapContainer, TileLayer, Marker, Popup} from 'react-leaflet';

const position : LatLngExpression = [59.91174337077401, 10.750425582038146];

export default function MapJar() {
    return (
        <MapContainer center={position} zoom={13} scrollWheelZoom={false}>
            <TileLayer
                attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
                url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
            />
            <Marker position={position}>
                <Popup>
                    A pretty CSS3 popup. <br /> Easily customizable.
                </Popup>
            </Marker>
        </MapContainer>
    );
};

我尝试了多次重新安装依赖项,但仍然无法正常工作。

我知道这是一个简单的问题和我所犯的错误,但是,我一直没有能够解决这个错误。


1
这似乎是CRA的一个未解决问题。另一方面,@react-leaflet/core模块具有ES2019的tsconfig目标,这意味着当构建包时,??运算符应该已被转译为其他内容。我认为应该在react-leaflet存储库上开启一个问题,指出该行似乎没有按照tsconfig规定正确编译为ES2019。 - Seth Lutske
2
谢谢@SethLutske!我在几个小时前发现了完全相同的问题,链接如下:https://github.com/PaulLeCam/react-leaflet/issues/877 - Gimhan Wijayawardana
18个回答

112
我找到了解决方法。
修复步骤:
1. 打开你的package.json文件,并按以下方式编辑你的browserslist。 以下配置引用自?? Operator results in "Unexpected Token" err when used in package #9468,最初建议者为bkiac
 "browserslist": {
   "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
},

to

"browserslist": [
   ">0.2%",
  "not dead",
  "not op_mini all"
],
  1. 完成后,删除 node_modules/.cache 目录。

  2. 然后尝试运行 npm install

  3. 最后运行 npm start

完成啦!

参考文献:


1
你尝试过删除 node_modules/.cache 目录吗?@hoogw - Gimhan Wijayawardana
8
我尝试了这个方法,但当我执行 npm start 时,会弹出提示框: "We're unable to detect target browsers. Would you like to add the defaults to your package.json? › (Y/n)"。如果我选择否,CRA就会退出,并显示消息:"As of react-scripts >=2 you must specify targeted browsers. Please add a browserslist key to your package.json." 如果我选择是,它会将我的 package.json 覆盖回原来的状态,继续运行,然后再次失败并显示相同的消息。这是使用 react-scripts 4.0.1 时出现的情况。有人遇到过类似问题吗?你有什么建议? - Seth Lutske
2
对我有用,谢谢!rm -rf node_modules/.cache/ 是必要的 - Bilbo
2
我的 package.json 已经看起来像你指出的那样了。我的错误和 OP 的一样仍然存在...我已经尝试删除缓存文件夹和完全删除 node_modules,但它仍然无法工作。 - Rick
1
只需删除开发内容 "development": [] - Adrien Leloir
显示剩余5条评论

31

这个问题似乎最终与 create-react-app 以及它打包文件的方式有关,如果你将浏览器目标从原来的更换为:

"browserslist": {
   "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
},

为了。
"browserslist": [
   ">0.2%",
  "not dead",
  "not op_mini all"
],

然后停止服务器并重新运行它。

感谢bkiac在官方 create-react-app GitHub 问题中指出了此问题的解决方法。

您可以通过下载这个codesandbox示例来重现该错误和修复过程。当您打开它时,它可以正常工作,但是如果您将其下载并在本地运行,则可以使用package.json中的第一个 browserslist选项看到错误。如果您停止服务器,将browserslist选项替换为新的选项,并重新运行应用程序,您会发现它按预期工作。


3
如果移除开发对象,在我的情况下,React会提示以下信息:“在react-scripts版本>=2时,你必须指定目标浏览器。” 然后程序退出。请问你使用的是哪个版本的react-scripts?请告知。 - Apokalos
2
"react-leaflet": "^3.2.0" and "react-scripts": "4.0.3" - kboul
3
建议你也应该删除缓存:node_modules/.cache。这对我有用。 - Daan Wiltenburg

21

在我进行npm更新后,我遇到了这个问题。

安装了以下这些包: "react-leaflet": "^3.2.0"

并作为依赖项(在.lock中找到): "@react-leaflet/core": "1.1.0",

强制npm使用这些版本,对我有用:

"@react-leaflet/core": "1.0.2",

"react-leaflet": "3.1.0",

所以尝试执行命令npm i react-leaflet@3.1.0 @react-leaflet/core@1.0.2


3
感谢@SchitzelKraft!这是在尝试了许多其他方法后对我有效的解决方案。其中一个我认为很有前途的是https://dev59.com/31EG5IYBdhLWcg3wWa5H#67991412,但它没有解决我的问题。 - Mugabo

11

我通过更改 browserslist 以解决问题,就像其他人所述的那样。我的 browserslist 现在看起来像这样:

"browserslist": [
  ">0.2%",
  "not dead",
  "not op_mini all"
]

接着我做了以下步骤:

  1. 删除你的node_modules文件夹
  2. 运行npm cache clean --force
  3. 运行npm install

现在一切应该按预期工作。如果地图没有加载,请不要忘记将leaflet CSS和JavaScript添加到您的页面并为地图容器设置高度。有关更多信息,请参见官方文档


8

需要翻译的内容:

黑客您的browserslist或降级软件包并不是处理不针对合理JS版本的模块的安全或长期解决方案。jlahd's answer非常好,除了react-app-rewire-babel-loader已被其作者停止支持。您可以使用customize-cra更轻松地实现相同的结果(无论如何,您都应该使用CRA,因为这是配置您的内容安全策略的唯一方法),使用babelInclude:

// config-overrides.js

const { babelInclude, override } = require('customize-cra');
const path = require('path');

module.exports = {
  webpack: override(
    babelInclude([
      path.resolve('src'),
      path.resolve('node_modules/@react-leaflet'),
      path.resolve('node_modules/react-leaflet')
    ])
    // and configure other stuff here like csp-html-webpack-plugin
  ),
};

1
我很欣赏你的推理和解决问题的方法--那些只是在设置上进行修改而没有解决潜在问题的快速修复并不是前进的方式。我即将尝试这个解决方案,如果对我有效,我会让你知道的。 - Mugabo
1
我仍然遇到完全相同的问题:“编译失败”,并指向 ./node_modules/@react-leaflet/core/esm/path.js 10:41 Module parse failed: Unexpected token (10:41) - Mugabo
1
与原帖的一个不同之处在于我的文件正在被另一个加载器处理(这超出了我的理解范围):“文件已使用以下加载器进行处理:
  • ./node_modules/react-scripts/node_modules/babel-loader/lib/index.js 您可能需要另一个加载器来处理这些加载器的结果。”
- Mugabo
1
你的npm脚本是否使用了react-app-rewired而不是react-scripts?我在我的一个内部项目中正好使用了上面的文件(因此不需要CSP相关的内容)。 - Trevor Robinson
1
我没有手动更改它们。安装 customize-cra 和 react-app-rewired 会更改它们吗?最终,我选择了 @SchitzelKraft 的解决方案(在上面的 https://dev59.com/31EG5IYBdhLWcg3wWa5H#67689949),并在删除 node-modules 并清除缓存后,版本更改起作用了。我想测试您的解决方案,并确保替换了 react-scripts。 - Mugabo
1
你需要手动更改它们为 react-app-rewired:https://github.com/timarney/react-app-rewired#3-flip-the-existing-calls-to-react-scripts-in-npm-scripts-for-start-build-and-test - Trevor Robinson

4

我遇到了同样的问题,但是这里提出的所有解决方案都没有让我信服。所以我用以下方法解决了它:

yarn add -D @babel/plugin-proposal-nullish-coalescing-operator

然后我将它添加到 babel.config.js 中的 Babel 插件中:

module.exports = {
  presets: [
    // ... some presets here
  ],
  plugins: [
    // ... any plugins here
    '@babel/plugin-proposal-nullish-coalescing-operator',
  ],
  env: {
    // ... your configuration
  },
}

问题出现了,因为该库正在使用空值合并(??)操作符,我应该将其添加到Webpack的bable-loader排除列表中。

// webpack.common.js

module.exports = {
   // ... some configuration here
    module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        // the @react-leaflet and react-leaflet libraries must be excluded.
        exclude: /node_modules\/(?!(@react-leaflet|react-leaflet)\/)/i,
        use: []
      }
    ],
   // ... more configuration here

}

1
不确定如何将其应用于Storybook,尽管它似乎是最合理的解决方案。 - Eric Burel

3

这并不是针对原问题的直接解决方案(这些指令适用于create-react-app (CRA) 项目),但我还是写下了答案,以防其他 CRA 用户也遇到类似问题。

  • 我不想强制使用旧版本的react-leaflet
  • 几个答案中提供的浏览器列表更改建议并不适用于我,因为我正在使用create-react-appyarn start只会强制刷新配置)。
  • WITO 的建议 并没有直接起作用,原因是由于使用create-react-app,无法直接控制 Webpack/Babel 配置文件。
  • 从 CRA 中脱离出来可能是一个选择,但是我不愿意仅仅因为这个原因而走这条路。

最终可行的方法是使用两个库:react-app-rewiredreact-app-rewire-babel-loader。需要执行以下步骤:

  1. yarn add -D react-app-rewired react-app-rewire-babel-loader

  2. Change script names in package.json according to the instructions for react-app-rewired:

      /* package.json */
    
      "scripts": {
    -   "start": "react-scripts start",
    +   "start": "react-app-rewired start",
    -   "build": "react-scripts build",
    +   "build": "react-app-rewired build",
    -   "test": "react-scripts test",
    +   "test": "react-app-rewired test",
        "eject": "react-scripts eject"
    }
    
    
  3. Create config-overrides.js in the project's root according to instructions for react-app-rewire-babel-loader:

    /* config-overrides.js */
    
    const path = require("path");
    const fs = require("fs");
    const rewireBabelLoader = require("react-app-rewire-babel-loader");
    
    const appDirectory = fs.realpathSync(process.cwd());
    const resolveApp = relativePath => path.resolve(appDirectory, relativePath);
    
    module.exports = function override(config, env) {
        config = rewireBabelLoader.include(
            config,
            resolveApp("node_modules/@react-leaflet")
        );
        config = rewireBabelLoader.include(
            config,
            resolveApp("node_modules/react-leaflet")
        );
    
        return config;
    };
    

然后它就能工作了。基本上,这包括在 Babel 转译中使用 react-leaflet,并以与非 CRA 构建中WITO的答案相同的方式进行转译。


1
这是目前最好的答案,尽管 react-app-rewire-babel-loader 已不再支持 - Trevor Robinson

3

新增

"react-leaflet": ">=3.1.0 <3.2.0 || ^3.2.1",
"@react-leaflet/core": ">=1.0.0 <1.1.0 || ^1.1.1"

在 "package.json" 文件中

GitHub

第二个解决方案

如果您仍然遇到问题,可能是由于 package.json 文件。请确保它与以下文件相似:

 {
  "name": "my-app",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^5.12.0",
    "@testing-library/react": "^11.2.7",
    "@testing-library/user-event": "^12.8.3",
    "antd": "^4.15.6",
    "leaflet": "1.7.1",
    "leaflet.marker.slideto": "^0.2.0",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "react-leaflet": "3.0.2",
    "react-leaflet-drift-marker": "^3.0.0",
    "react-scripts": "4.0.3",
    "web-vitals": "^1.1.2"
  },
  "devDependencies": {
    "typescript": "3.8.3"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
  },
  "browserslist": [
    ">0.2%",
    "not dead",
    "not ie <= 11",
    "not op_mini all"
  ]
}

2
安装完react-leaflet后,现有的package.json文件将变成这样:
 "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },

但是运行时会出现以下错误:
 ./node_modules/@react-leaflet/core/esm/path.js 10:41
Module parse failed: Unexpected token (10:41)
File was processed with these loaders:
 * ./node_modules/babel-loader/lib/index.js
You may need an additional loader to handle the result of these loaders.
|   useEffect(function updatePathOptions() {
|     if (props.pathOptions !== optionsRef.current) {
>       const options = props.pathOptions ?? {};
|       element.instance.setStyle(options);
|       optionsRef.current = options;

为了修复这个 bug,需要将上面的 package.json 文件改为以下内容(作为一个数组):
"browserslist": [
    ">0.2%",
    "not dead",
    "not op_mini all"
  ],
  1. 然后,前往node_modules文件夹并删除.cache文件夹。
  2. 使用Ctrl + C停止服务器。
  3. 再次执行npm install

1
在React-Leaflet(RL)的源代码中,使用了null合并运算符,但特定版本的Acorn不支持该运算符。
有关详细信息,请查看nnatter在此处的解释:

https://github.com/PaulLeCam/react-leaflet/issues/883

解决问题的方法:

  1. use nnater's suggested solution:

    https://babeljs.io/docs/en/babel-plugin-proposal-nullish-coalescing-operator

    or

  2. instead of using the official React-Leaflet package, you can use

     npm install --save @monsonjeremy/react-leaflet
    

    From

    https://www.npmjs.com/package/@monsonjeremy/react-leaflet

    which is a fork of RL 3.2.1.

那样做,您就不需要降级,也不需要做有趣的事情。

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