服务器端渲染:节点语法错误:无法在模块外使用导入语句

Ben*_*off 6 reactjs babeljs esm

所以经过几天或谷歌搜索并自己尝试一些不同的设置后,我无法修复此错误。

背景:我正在编写一个带有服务器端渲染的 React 应用程序。我曾经写过很多 React 应用程序,但只使用客户端渲染,但对于一个新项目,我决定尝试 SSR 并且它可以工作,直到我添加Formik到混合中,导入lodash-es. 在深入挖掘之后,似乎 ES 模块node_modules没有被“转译”,因此当服务器运行时它会崩溃,因为节点似乎无法导入它。这是错误:

$ cross-env NODE_ENV=development webpack --config webpack.config.js --mode=development
$ node dist/server.js
.../node_modules/lodash-es/isPlainObject.js:1
import baseGetTag from './_baseGetTag.js';
^^^^^^

SyntaxError: Cannot use import statement outside a module
    at wrapSafe (node:internal/modules/cjs/loader:1018:16)
    at Module._compile (node:internal/modules/cjs/loader:1066:27)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1131:10)
    at Module.load (node:internal/modules/cjs/loader:967:32)
    at Function.Module._load (node:internal/modules/cjs/loader:807:14)
    at Module.require (node:internal/modules/cjs/loader:991:19)
    at require (node:internal/modules/cjs/helpers:92:18)
    at eval (webpack://@nesta-se/admin/external_%22lodash-es/isPlainObject%22?:1:18)
    at Object.lodash-es/isPlainObject (/Users/benjamin/GitHub/nesta-admin/build/server.js:809:1)
    at __webpack_require__ (/Users/benjamin/GitHub/nesta-admin/build/server.js:1077:32)
Run Code Online (Sandbox Code Playgroud)

我使用 Webpack 和 Babel 来转译我的代码。

babel.config.js

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "useBuiltIns": "usage",
        "debug": true,
        "corejs": 3,
        "targets": {
          "browsers": [
            "last 2 versions"
          ],
          "node": "current"
        }
      }
    ],
    "@babel/preset-react"
  ],
  "plugins": [
    "@babel/plugin-syntax-dynamic-import",
    "lodash",
    [
      "babel-plugin-styled-components",
      {
        "displayName": true,
        "ssr": true
      }
    ]
  ]
}
Run Code Online (Sandbox Code Playgroud)

webpack.config.js

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "useBuiltIns": "usage",
        "debug": true,
        "corejs": 3,
        "targets": {
          "browsers": [
            "last 2 versions"
          ],
          "node": "current"
        }
      }
    ],
    "@babel/preset-react"
  ],
  "plugins": [
    "@babel/plugin-syntax-dynamic-import",
    "lodash",
    [
      "babel-plugin-styled-components",
      {
        "displayName": true,
        "ssr": true
      }
    ]
  ]
}
Run Code Online (Sandbox Code Playgroud)

这是我的依赖项 package.json

const path = require('path');
const webpack = require('webpack');
const { merge } = require('webpack-merge');
const nodeExternals = require('webpack-node-externals');

var common = {
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules\/(?!lodash-es)/,
        include: path.resolve(__dirname, 'src'),
        use: ['babel-loader'],
      },
      // {
      //   test: /\.(gif|png|jpe?g|svg)$/i,
      //   use: ['file-loader'],
      // },
    ],
  },
  mode: 'development',

  output: {
    chunkFilename: '[chunkhash].js',
    // https://reactjs.org/docs/cross-origin-errors.html
    crossOriginLoading: 'anonymous',
    filename: '[name].js',
    publicPath: '/',
  },
};

var server = merge(common, {
  name: 'server',
  target: 'node',
  externals: [nodeExternals()],

  entry: {
    server: path.resolve(__dirname, 'src', 'server.js'),
  },

  output: {
    filename: 'server.js',
    path: path.resolve('build'),
    publicPath: '/',
  },

  plugins: [
    new webpack.HotModuleReplacementPlugin(),
  ],

  node: {
    global: false,
    __filename: false,
    __dirname: false,
  },
});

var client = = merge(common, {
  devtool: 'cheap-module-source-map',
  devServer: {
    hot: true,
  },
  name: 'client',
  target: 'web',

  entry: {
    client: [
      'react-hot-loader/babel',
      'webpack-hot-middleware/client',
      path.resolve('src', 'client.js'),
    ],
  },

  output: {
    filename: '[name].js',
    path: path.resolve('build'),
    publicPath: '/',
  },

  plugins: [new webpack.HotModuleReplacementPlugin()],

  optimization: {
    splitChunks: {
      cacheGroups: {
        vendor: {
          chunks: 'initial',
          name: 'vendor',
          test: (module) => /node_modules/.test(module.resource),
          enforce: true,
        },
      },
    },
  },
});

module.exports = [client, server];
Run Code Online (Sandbox Code Playgroud)