Yarn2环境执行rollup -c报错Cannot find module 'react'如何解决
Yarn2环境下React组件库Rollup构建问题解答
问题背景
在Yarn2环境下开发React组件库,直接执行yarn rollup -c会抛出找不到react模块的TS2307错误,先执行yarn tsc再执行rollup命令可规避该报错。
相关配置
1. tsconfig.json
{ "compilerOptions": { "declaration": true, "declarationDir": "dist/types", "target": "es5", "lib": ["dom", "dom.iterable", "esnext"], "skipLibCheck": true, "esModuleInterop": true, "allowSyntheticDefaultImports": true, "strict": true, "module": "es6", "moduleResolution": "node", "resolveJsonModule": true, "jsx": "react", "typeRoots": ["@types"], "noImplicitAny": false, "baseUrl": ".", "paths": { "@/*": ["/*"], "~/*": ["src/*"] }, }, "include": ["**/*.tsx", "**/*.ts", "@types", "index.ts", "src/index.ts"], "exclude": ["build", "dist", "lib", "**/stories", "**/*.stories.tsx", "rollup.config.js"] }
2. rollup.config.js
import pkg from './package.json'; import typescript from 'rollup-plugin-typescript2'; import peerDepsExternal from 'rollup-plugin-peer-deps-external'; import postcss from 'rollup-plugin-postcss'; import postcssPrefixer from 'postcss-prefixer'; import resolve from '@rollup/plugin-node-resolve'; import commonjs from '@rollup/plugin-commonjs'; import json from '@rollup/plugin-json'; import babel from 'rollup-plugin-babel'; import svgr from '@svgr/rollup'; import url from 'rollup-plugin-url'; const extensions = ['.js', '.jsx', '.ts', '.tsx', '.scss']; process.env.BABEL_ENV = 'production'; function setUpRollup({ input, output }) { return { input, output, watch: { include: '*', exclude: '.yarn/**' }, plugins: [ peerDepsExternal(), json(), resolve({ extensions }), commonjs(), babel({ extensions, runtimeHelpers: true }), url(), svgr(), typescript({ exclude: [ '**/stories', '**/*.stories'], useTsconfigDeclarationDir: true }), postcss({ extract: true, modules: true, sourceMap: true, use: ['sass'], plugins: [ postcssPrefixer({ prefix: `${pkg.name}__`, }), ], }), ], external: ['react', 'react-dom'], }; }; export default [ setUpRollup({ input: 'src/index.ts', output: { file: pkg.cjs, sourcemap: true, format: 'cjs', }, }), setUpRollup({ input: 'src/index.ts', output: { file: pkg.esm, sourcemap: true, format: 'esm', }, }), ];
3. package.json
{ "name": "custom-reactfullpage.js", "version": "1.0.0", "cjs": "dist/cjs.js", "esm": "dist/esm.js", "main": "dist/index.js", "repository": "https://github.com/remigailard80/fullpageLib.js", "author": "KIMMINSEOK", "license": "NO LICENSE", "types": "dist/types/index.d.ts", "module": "dist/cjs.js", "type": "module", "files": [ "/dist" ], "devDependencies": { "@babel/core": "^7.15.0", "@mdx-js/react": "^1.6.22", "@rollup/plugin-commonjs": "^20.0.0", "@rollup/plugin-json": "^4.1.0", "@rollup/plugin-node-resolve": "^13.0.4", "@storybook/addon-actions": "^6.3.8", "@storybook/addon-docs": "^6.3.8", "@storybook/addon-essentials": "^6.3.8", "@storybook/addon-links": "^6.3.8", "@storybook/cli": "^6.3.8", "@storybook/react": "^6.3.8", "@svgr/rollup": "^5.5.0", "@types/esm": "^3", "@types/jest": "^27.0.1", "@types/mdx-js__react": "^1", "@types/node": "^16.7.10", "@types/react": "^17", "@types/react-dom": "^17.0.9", "@yarnpkg/pnpify": "^3.0.1-rc.2", "@yarnpkg/sdks": "^2.4.2-rc.2", "babel-loader": "^8.2.2", "babel-preset-react-app": "^10.0.0", "esm": "^3.2.25", "postcss": "^8.3.6", "postcss-prefixer": "^2.1.3", "react": "^17.0.2", "react-docgen-typescript-loader": "^3.7.2", "react-dom": "^17.0.2", "rollup": "^2.56.3", "rollup-plugin-babel": "^4.4.0", "rollup-plugin-commonjs": "^10.1.0", "rollup-plugin-node-resolve": "^5.2.0", "rollup-plugin-peer-deps-external": "^2.2.4", "rollup-plugin-postcss": "^4.0.1", "rollup-plugin-typescript2": "^0.30.0", "rollup-plugin-url": "^3.0.1", "typescript": "^4.4.2" }, "peerDependencies": { "react": "*", "react-dom": "*" }, "scripts": { "sb": "start-storybook -p 6006", "build-storybook": "build-storybook" } }
问题解答
1. 为什么先执行yarn tsc就能规避找不到react模块的报错?
Yarn2默认使用PNP模式管理依赖,所有依赖路径都由pnp.cjs统一解析。yarn tsc调用的是Yarn SDK包装过的TypeScript实例,执行时会自动加载pnp.cjs的解析逻辑,能正确识别PNP管理的react及其类型文件,同时会生成TS模块解析缓存和类型产物。
而rollup-plugin-typescript2默认会优先使用自身依赖的typescript实例,不会调用Yarn SDK的TS版本,因此直接执行rollup时无法识别PNP的依赖路径,抛出找不到模块的错误。先执行过yarn tsc后,rollup-plugin-typescript2会复用已生成的TS缓存和类型产物,不需要重新走全量模块解析,因此不会触发报错。
2. 如何配置才能无需提前执行tsc,直接执行rollup命令完成构建?
以下三个方案任选其一即可:
- 方案1:指定rollup使用Yarn SDK的TypeScript实例
修改rollup.config.js中typescript插件的配置,手动指定TS来源:
用yarn执行rollup时,typescript({ exclude: [ '**/stories', '**/*.stories'], useTsconfigDeclarationDir: true, typescript: require('typescript') // 新增该行 })require('typescript')会自动指向Yarn SDK包装的TS实例,加载PNP解析逻辑。 - 方案2:用pnpify包装rollup命令
在package.json的scripts中新增构建命令,用pnpify注入PNP解析能力:"scripts": { "build": "yarn pnpify rollup -c" } - 方案3:兼容传统node_modules模式
在项目根目录的.yarnrc.yml中添加配置nodeLinker: node-modules,执行yarn install重新生成node_modules目录,即可和传统包管理器行为一致,无需额外适配。
内容的提问来源于stack exchange,提问作者djangoboi
相关产品推荐
相关产品推荐

