使用yarn工作区将ui库与汇总捆绑在一起时,导入时未定义

时间:2018-06-25 06:34:23

标签: javascript reactjs yarnpkg rollupjs yarn-workspaces

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

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

  

TypeError:无法读取未定义的属性“ NavBar”       在应用程序上[0](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>
);

root package.json:

{
  "name": "project",
  "version": "1.0.0",
  "private": true,
  "workspaces": [
    "packages/*"
  ]
}

UI package.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"
  }
}

网络应用程序package.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"
  ]
}

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

问候 山茱

1 个答案:

答案 0 :(得分: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,因此您由于您将未定义传递给导出,因此出现错误Cannot read property 'NavBar' of undefined [0]

这是通过插件“ add-module-exports”完成的,如果您确实需要module.exports,则这是必需的(除非存在NodeJS或某些RequireJS,否则不需要。)

要使其正常运行,只需从项目用户界面"add-module-exports"中的插件中删除.babelrc