#reactjs #babeljs #es6-modules
#reactjs #babeljs #es6-модули
Вопрос:
итак, после нескольких дней поиска или поиска в Google и пробования некоторых других настроек я не могу исправить эту ошибку.
Предыстория: я пишу приложение 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_"lodash-es/isPlainObject"?: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)
Я использую 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
}
]
]
}
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];
И это зависимости от моего 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"
},
Комментарии:
1.Почему вы
exclude
, а неinclude
lodash-es
для решения этой проблемы? Если это не исправит проблему, то, что я обычно делаю для отладки подобных проблем, — это удалитьexclude
иtest
т. Д. И Использоватьfunction
для myinclude
, который делает все вместо этого. Это помогает мне понять, что в настоящее время используется, а что нет, примерно так:ignore: [function shouldIgnore(modulePath, ...otherArgs) { const shouldIgnore = /* your ignore logic goes here */; console.log('[BABEL]', modulePath, shouldIgnore); return shouldIgnore; }]
2.В случае, если ваша
babel
конфигурация по умолчанию имеет некоторый конфликт сlodash-es
, просто добавьте отдельныйbabel-loader
rule
с его собственной конфигурацией, возможно, просто сpreset-env
, чтобы позаботиться оimport
операторах.3. ПРИМЕЧАНИЕ: я только что осознал свою ошибку наблюдения — негативный прогноз в вашем
exclude
. У меня был худший опыт использования регулярных выражений в babelexclude
иinclude
. С другой стороны, я обнаружил, чтоinclude
функциональное решение всегда работало (по крайней мере, после достаточной отладки).