javascript - 使用纱线工作区将 ui 库与汇总捆绑时导入未定义
问题描述
对于一个新项目,我开始使用汇总来捆绑 UI 库并在反应应用程序中使用该库。我还在使用 yarn 工作区来管理 UI 库和 Web 应用程序之间的内部依赖关系。
当我尝试在我的 Web 应用程序中使用 UI 库时,导入返回未定义并引发“无法从未定义中获取”错误。
类型错误:无法在 App (C:/Users/user/dev/project/packages/project-web/src/pages/App.jsx:9:6) 读取未定义 [0] 的属性“NavBar”
网络应用代码:
import React from 'react';
import {NavBar} from 'project-ui';
const App = () => (
<div>
<NavBar/>
<div>App component!x</div>
</div>
);
根包.json:
{
"name": "project",
"version": "1.0.0",
"private": true,
"workspaces": [
"packages/*"
]
}
用户界面包.json:
{
"name": "project-ui",
"version": "1.0.0",
"main": "dist/project-ui.cjs.js",
"jsnext:main": "dist/project-ui.es.js",
"module": "dist/project-ui.es.js",
"files": ["dist"],
"scripts": {
"build": "rollup -c"
},
"peerDependencies": {
"react": "16.3.2",
"react-dom": "16.3.2"
},
"devDependencies": {
"babel-core": "6.26.3",
"babel-plugin-external-helpers": "6.22.0",
"babel-preset-env": "1.6.1",
"babel-preset-react": "6.24.1",
"babel-preset-stage-2": "6.24.1",
"rollup": "0.60.0",
"rollup-plugin-babel": "3.0.4",
"rollup-plugin-commonjs": "9.1.3",
"rollup-plugin-node-resolve": "3.0.0",
"rollup-plugin-replace": "2.0.0",
"rollup-plugin-uglify": "4.0.0"
}
}
网络应用程序包.json:
{
"name": "project-web",
"version": "1.0.0",
"scripts": {
"build": "webpack --colors --display-error-details --config=webpack/webpack.dev.js",
"dev": "concurrently --kill-others \"npm run dev:start\"",
"dev:start": "node ./server/index.js"
},
"dependencies": {
"babel-polyfill": "^6.26.0",
"express": "^4.16.3",
"react": "^16.3.2",
"react-dom": "^16.3.2",
"project-ui": "1.0.0"
},
"devDependencies": {
"babel-core": "^6.26.3",
"babel-eslint": "^8.2.3",
"babel-loader": "^7.1.4",
"babel-plugin-add-module-exports": "^0.2.1",
"babel-plugin-dynamic-import-node": "^1.2.0",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-env": "^1.6.1",
"babel-preset-react": "^6.24.1",
"concurrently": "^3.5.1",
"eslint": "^4.19.1",
"eslint-loader": "^2.0.0",
"eslint-plugin-react": "^7.7.0",
"piping": "^1.0.0-rc.4",
"webpack": "^4.6.0",
"webpack-cli": "^2.0.15",
"webpack-dev-middleware": "^3.1.3",
"webpack-dev-server": "^3.1.3",
"webpack-hot-middleware": "^2.22.1",
"webpack-node-externals": "^1.7.2"
}
}
汇总配置:
import resolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import babel from 'rollup-plugin-babel';
import replace from 'rollup-plugin-replace';
import { uglify } from 'rollup-plugin-uglify';
import pkg from './package.json'
const FORMATS = {
UMD: 'umd',
ES: 'es',
CJS: 'cjs'
};
const allowedFormats = [FORMATS.UMD, FORMATS.ES, FORMATS.CJS];
const bundle = (fileFormat, {format, minify}) => {
if (!allowedFormats.includes(format)) {
throw new Error(`Invalid format given: ${format}`);
}
const shouldMinify = minify && format === FORMATS.UMD;
const externals = format === FORMATS.UMD
? Object.keys(pkg.peerDependencies || {})
: [
...Object.keys(pkg.dependencies || {}),
...Object.keys(pkg.peerDependencies || {})
];
return {
input: 'src/index.js',
output: {
file: fileFormat.replace('{format}', shouldMinify ? `${format}.min` : format),
format,
name: 'project-ui',
exports: 'named',
globals: {
react: 'React',
'prop-types': 'PropTypes'
}
},
external: externals,
plugins: [
resolve({ jsnext: true, main: true }),
commonjs({ include: 'node_modules/**' }),
babel({
exclude: 'node_modules/**',
}),
format === FORMATS.UMD
? replace({'process.env.NODE_ENV': JSON.stringify(shouldMinify ? 'production' : 'development')})
: null,
shouldMinify ? uglify() : null
].filter(Boolean)
};
};
export default [
bundle('dist/project-ui.{format}.js', {format: FORMATS.UMD, minify: true}),
bundle('dist/project-ui.{format}.js', {format: FORMATS.CJS}),
bundle('dist/project-ui.{format}.js', {format: FORMATS.ES})
];
从汇总实际生成的代码:
import React from 'react';
var NavBar = function NavBar() {
return React.createElement(
'header',
null,
'nav bar'
);
};
module.exports = exports['default'];
export { NavBar };
原始导航栏:
import React from 'react';
const NavBar = () => (
<header>
nav bar
</header>
);
export default NavBar;
index.js:
export { default as NavBar} from './NavBar/NavBar';
.babelrc:
{
"presets": [
["env", {
"loose": true,
"modules": false,
"targets": {
"browsers": ["last 2 versions"]
}
}],
"react",
"stage-2"
],
"plugins": [
"transform-runtime",
"add-module-exports",
"external-helpers"
]
}
生成的汇总代码看起来没问题,所以我认为这是一个纱线问题,但我不确定。任何帮助,将不胜感激!
问候康奈尔
解决方案
问题一定出在您使用 babel/rollup 转换代码的方式上。我有一个活生生的例子,说明您的代码在在线 babel中的外观:
为我生成的代码是:
import React from 'react';
const NavBar = () => React.createElement(
'header',
null,
'nav bar'
);
export default NavBar; // first define default and then we assign export['default']
module.exports = exports['default'];
请注意,在此代码中,我们首先将 export default 分配给所需的值,然后分配 export['defaults'] (当我调试您的示例时,我得到的export['default']
是undefined
,因此您收到错误Cannot read property 'NavBar' of undefined [0]
,因为您将 undefined 传递给 export.
这是由插件'add-module-exports'完成的,如果你真的需要module.exports,这是必要的(除非存在NodeJS或一些RequireJS,否则不应该需要)。
为了使其工作,只需"add-module-exports"
从 project-ui 中的插件中删除.babelrc
。
推荐阅读
- javascript - 如何在 jQuery 中仅提取 window.location.pathname 的最后一部分?(内有详细说明)
- r - 更新R中等效列的表
- c++ - 我可以继承 std::string 以添加一些额外的成员/标志吗?
- swift - Swift: Dismiss a FormViewController in Eureka-forms
- javascript - 这段代码如何运行改变检测角度?
- oracle - AWS lambda - 如何从 lambda 连接内部 oracle 实例(比如 VPN / 内部办公网络)
- excel - 宏只填充一个单元格,而不是在应该结束的时候结束
- security - TrackJS 和 GDPR 和 SPA
- side-menu - 如何使用 JonkyKong/SideMenu - SideMenuPresentationStyle.menuSlideIn?
- javascript - Jquery - 如何替换选定元素的值然后提交