求助:Babel无法转译本地包代码,Webpack构建报JSX语法错误
Problem Overview
I'm working with a project structure that includes a local package linked via yarn link, but when running webpack --mode production, I get a SyntaxError pointing to untranspiled JSX in my local package. Here's the full breakdown:
Project Directory Structure
/testproject /local-package package.json /src package.json
Root package.json Dependency
"dependencies": { "local-package": "file:./local-package" }
Webpack Configuration (Relevant Section)
module: { rules: [ { test: /\.jsx?$/, exclude: /node_modules(?!\/local-package)/, use: ["babel-loader"] } ] }
Error Output
ERROR in ./local-package/components/NotFound.jsx Module build failed: SyntaxError: /Users/pavel/Projects/JS/testproject/local-package/components/NotFound.jsx: Unexpected token (4:2) 2 | 3 | const NotFound = () => ( > 4 | <div> | ^ 5 | <h3>404 page not found</h3> 6 | <p>We are sorry but the page you are looking for does not exist.</p> 7 | </div>
Reproduction Steps
- Clone the repository:
git clone https://github.com/perevezencev/webpack-error.git - Run
yarn linkin/webpack-error/local-package - Run
yarn link "local-package"in/webpack-error - Run
yarnin/webpack-error - Run
yarn buildin/webpack-error
Let's Fix This!
The root issue here is how yarn link handles symlinks combined with your Webpack exclude rule. When you link the local package, it gets symlinked into your root project's node_modules—but Webpack doesn't recognize the symlinked path as part of node_modules/local-package (since symlinks resolve to the actual filesystem location). That means your exclude regex skips transpiling the local package's JSX, hence the SyntaxError.
Here are two solid fixes to choose from:
1. Make Webpack's Exclude Rule Symlink-Friendly
Instead of relying on a regex that looks for node_modules/local-package directly, use a custom function to check if the module path belongs to your local package—regardless of symlinks:
module: { rules: [ { test: /\.jsx?$/, exclude: (modulePath) => { // Skip node_modules unless the path includes our local-package return /node_modules/.test(modulePath) && !/local-package/.test(modulePath); }, use: ["babel-loader"] } ] }
This function checks every module path: if it's in node_modules but doesn't reference local-package, it gets excluded. If it does reference local-package (even via symlink), Babel will transpile its JSX.
2. Pre-Transpile Your Local Package
Another approach is to ensure your local package comes with pre-transpiled code. Add a Babel config to /local-package and set up a script to build it automatically:
- First, install Babel dependencies in the local package:
cd local-package yarn add --dev @babel/cli @babel/preset-env @babel/preset-react
- Create a
.babelrcfile in/local-package:
{ "presets": ["@babel/preset-env", "@babel/preset-react"] }
- Update
/local-package/package.jsonto point to the transpiled code and add a prepare script:
{ "main": "dist/index.js", "scripts": { "prepare": "babel src --out-dir dist" } }
The prepare script runs automatically when you link or install the package, so every time you make changes to the local package, it will transpile the JSX to plain JS before your root project uses it.
Quick Recap
Your original regex worked for direct file: dependencies, but yarn link uses symlinks that break the path matching. Either adjust Webpack to recognize the local package regardless of location, or pre-transpile the package to avoid needing Webpack to process its JSX.
内容的提问来源于stack exchange,提问作者Pavel Perevezencev

