使用纱线工作区将 ui 库与汇总捆绑时导入未定义

Posted

技术标签:

【中文标题】使用纱线工作区将 ui 库与汇总捆绑时导入未定义【英文标题】:import undefined when bundling ui library with rollup using yarn workspaces 【发布时间】:2018-12-03 16:17:52 【问题描述】:

对于一个新项目,我开始使用汇总来捆绑 UI 库并在反应应用程序中使用该库。我还在使用 yarn 工作区来管理 UI 库和 Web 应用程序之间的内部依赖关系。

当我尝试在我的网络应用程序中使用 UI 库时,导入返回未定义并引发“无法从未定义中获取”错误。

TypeError:无法读取未定义的属性“NavBar” [0] 在 App (C:/Users/user/dev/project/packages/project-web/src/pages/App.jsx:9:6)

webapp 代码:

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/*"
  ]

UI 包.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"
  ]

生成的汇总代码看起来没问题,所以我认为这是一个纱线问题,但我不确定。任何帮助将不胜感激!

问候 康奈尔

【问题讨论】:

exports['default'] 返回什么? ;) 能否贴出 NavBar 的原始代码(不是 RollUp 生成的代码) 另外,你能发布你的 babel 配置吗?在生成它之后,我无法以任何方式获得与您相同的代码,这可能是问题 我添加了原始代码和 babel 配置。感谢您的回复! @GuyT 当我在生成的代码末尾添加日志时,exports['default'] 的值是 NavBar: [Function: NavBar] 【参考方案1】:

问题一定出在您使用 babel/rollup 转译代码的方式上。我有一个活生生的例子,说明您的代码在online 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,因此您会收到错误 @ 987654325@,因为您将 undefined 传递给导出。

这是由插件'add-module-exports'完成的,如果你真的需要module.exports,这是必要的(除非存在NodeJS或一些RequireJS,否则不应该需要它)。

为了使它工作,只需从你的插件中删除"add-module-exports" 项目-ui .babelrc

【讨论】:

感谢您的帮助!

以上是关于使用纱线工作区将 ui 库与汇总捆绑时导入未定义的主要内容,如果未能解决你的问题,请参考以下文章

从库导入的 React 组件的 Material-Ui 主题化问题

Rails 6 无法导入纱线依赖项:未捕获错误:模块解析失败:意外字符“#”(1:0)

Docker未安装纱线

元素 UI 测试抛出 ReferenceError: 消息未定义

Pyspark UDF 广播变量未定义仅在由单独脚本导入时

纱线未安装在 nvm 版本节点版本中