NextJS引入自研NPM库报错:Cannot use import statement outside a module
Next.js引入自研ESM库时出现"Cannot use import statement outside a module"错误
错误详情
error - /Users/apple/testing-build/node_modules/foobar/dist/some-library.es.js:1 import t, { useState as M } from "react"; ^^^^^^ SyntaxError: Cannot use import statement outside a module at Object.compileFunction (node:vm:360:18) at wrapSafe (node:internal/modules/cjs/loader:1094:15) at Module._compile (node:internal/modules/cjs/loader:1129:27) ...
环境与已尝试方案
- Node版本:18.13.0
- 已尝试操作:将应用和库的
package.json中type字段设为module,或统一改为CJS规范,问题仍未解决
自研库相关配置
库的tsconfig.json
{ "compilerOptions": { "target": "ESNext", "useDefineForClassFields": true, "lib": ["DOM", "DOM.Iterable", "ESNext"], "allowJs": true, "skipLibCheck": true, "esModuleInterop": true, "allowSyntheticDefaultImports": true, "noFallthroughCasesInSwitch": true, "strict": true, "forceConsistentCasingInFileNames": true, "module": "ESNext", "moduleResolution": "Node", "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, "jsx": "react-jsx", "sourceMap": true, "baseUrl": ".", }, "include": ["./src/**/*.*"], "references": [{ "path": "./tsconfig.node.json" }] }
库的dist代码示例(ESM格式)
// Beginning parts imports the libraries required import t, { useState as D } from "react"; import l, { css as r } from "styled-components"; import { generateMedia as R } from "styled-media-query"; // .... // The Ending part exports the components export { ot as Accordian, Le as Badge, K as Button, nt as Card, lt as CollapsibleText, ct as Header, at as If };
库的Vite配置
import { resolve } from 'node:path'; import { defineConfig, loadEnv, splitVendorChunkPlugin } from 'vite'; import { externalizeDeps } from 'vite-plugin-externalize-deps'; import nodeResolve from '@rollup/plugin-node-resolve'; import commonjs from '@rollup/plugin-commonjs'; import dts from 'vite-plugin-dts'; import react from '@vitejs/plugin-react'; import * as pkg from './package.json'; function verifyEnv(mode) { switch (mode) { case 'test': case 'local': case 'production': case 'dev': { return true; } case 'development': { throw new Error( 'Seems like you provided mode as `development` means you probably wanted to use `dev` which is another script. Prefer our script over `vite dev`.' ); } default: { throw new Error( `Either you provided an incorrect environment or you didn't send anything. Env received was ${process.env.NODE_ENV}.` ); } } } export default defineConfig(({ mode }) => { verifyEnv(mode); const appEnv = loadEnv(mode, `${process.cwd()}/.env.${mode}`); return { build: { outDir: 'dist', rollupOptions: { input: './src/index.ts', treeshake: 'smallest', plugins: [nodeResolve({ mainFields: ['module', 'main'], browser: true }), commonjs()], output: { globals: { ...pkg.dependencies } } }, lib: { entry: resolve(process.cwd(), 'src/index.ts'), name: 'Foo Components', formats: ['es', 'umd'], fileName: (format) => `foo-components.${format}.js` } }, resolve: { alias: [ { find: '@src', replacement: resolve(__dirname, './src') }, { find: '@utils', replacement: resolve(__dirname, './src/utils') }, { find: '@themes', replacement: resolve(__dirname, './src/themes') }, { find: '@components', replacement: resolve(__dirname, './src/components') }, { find: '@dlsCss', replacement: resolve(__dirname, './src/design/dls.min.css') } ] }, plugins: [ react({ exclude: /\.stories\.(t|j)sx?$/, include: ['./src/**/*.tsx', './src/**/*.ts'], babel: { configFile: true } }), dts({ include: ['./src/components'] }), splitVendorChunkPlugin(), externalizeDeps() ], define: { __APP_ENV__: appEnv } }; });
库的Babel配置
module.exports = { presets: [ [ '@babel/preset-env', { targets: { browsers: ['> 0.25%, not dead'] }, modules: false, corejs: '3.6.5', useBuiltIns: 'entry' } ], '@babel/preset-react', '@babel/preset-typescript' ], plugins: [ '@babel/plugin-proposal-optional-chaining', '@babel/plugin-syntax-optional-chaining', 'styled-components', '@babel/plugin-proposal-class-properties', '@babel/plugin-syntax-dynamic-import' ], env: { production: { only: ['app'], plugins: [ 'transform-react-remove-prop-types', '@babel/plugin-transform-react-inline-elements', '@babel/plugin-transform-react-constant-elements' ] }, test: { plugins: [ '@babel/plugin-transform-modules-commonjs', 'dynamic-import-node', [ 'auto-import', { declarations: [{ default: 'React', path: 'react' }] } ] ] } } };
Next.js应用配置(tsconfig.json)
{ "compilerOptions": { "target": "es5", // Also tried with `ESNext` "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, "skipLibCheck": true, "strict": true, "forceConsistentCasingInFileNames": true, "noEmit": true, "esModuleInterop": true, "module": "esnext", "moduleResolution": "node", "resolveJsonModule": true, "isolatedModules": true, "jsx": "preserve", "incremental": true, "baseUrl": ".", "paths": { "@/*": ["./src/*"] } }, "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], "exclude": ["node_modules"] }
求解决思路
需要解决在Next.js应用中引入该自研ESM库时的模块语法错误问题,恳请提供可行的排查方向或解决方案。
内容的提问来源于stack exchange,提问作者frostzt
相关产品推荐
相关产品推荐

