Server side rendering: node SyntaxError: Cannot use import statement outside a module

Viewed 510

so after several days or Googling and trying some different setups myself, I can not fix this error.

Background: I am writing a react app with server-side rendering. I used to write a lot of react apps but only with client-side rendering but for a new project I decided to give a shot to SSR and it works until I added Formik to the mix, that imports lodash-es. After digging deeper it seems ES modules in node_modules are not "transpiled" so when the server runs it crashes because node does not seem to be able to import it. Here is the error:

$ 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)

I use Webpack and Babel to transpile my code.

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
      }
    ]
  ]
}

webpack.config.js

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];

And this is the dependencies from my package.json:

"dependencies": {
    "compression": "^1.7.4",
    "cors": "^2.8.5",
    "express": "^4.17.1",
    "express-http-proxy": "^1.6.2",
    "file-loader": "^6.2.0",
    "formik": "^2.2.1",
    "isomorphic-fetch": "^3.0.0",
    "lodash": "^4.17.20",
    "method-override": "^3.0.0",
    "morgan": "^1.10.0",
    "react": "^16.13.0",
    "react-device-detect": "^1.14.0",
    "react-dom": "^16.13.0",
    "react-helmet": "^6.1.0",
    "react-is": "^17.0.1",
    "react-redux": "^7.2.0",
    "react-router-dom": "^5.1.2",
    "redux": "^4.0.5",
    "redux-freeze": "^0.1.7",
    "redux-logger": "^3.0.6",
    "styled-components": "^5.2.0"
  },
  "devDependencies": {
    "@babel/core": "^7.12.9",
    "@babel/preset-env": "^7.12.7",
    "@babel/preset-react": "^7.12.7",
    "@babel/runtime": "^7.12.5",
    "babel-loader": "^8.2.2",
    "babel-plugin-lodash": "^3.3.4",
    "babel-plugin-styled-components": "^1.12.0",
    "babel-preset-airbnb": "^5.0.0",
    "core-js": "^3.8.0",
    "cross-env": "^7.0.3",
    "nodemon": "^2.0.6",
    "npm-run-all": "^4.1.5",
    "react-hot-loader": "^4.13.0",
    "stylelint": "^13.7.2",
    "stylelint-config-recommended": "^3.0.0",
    "stylelint-config-styled-components": "^0.1.1",
    "stylelint-processor-styled-components": "^1.10.0",
    "webpack": "^5.10.0",
    "webpack-cli": "^4.2.0",
    "webpack-dev-middleware": "^4.0.2",
    "webpack-hot-middleware": "^2.25.0",
    "webpack-merge": "^5.2.0",
    "webpack-node-externals": "^2.5.2"
  },
0 Answers
Related