繁体   English   中英

如何将React组件导出为NPM包以在单独的项目中使用?

[英]How can I export a React Component as an NPM package to use in separate projects?

我在项目中创建了一个React组件,我想在多个项目中使用它。 目前,我只关心在本地和发展中做这件事。 React组件被渲染到根div中,项目使用webpack和babel将JSX,ES6和一些ES7功能转换成一个包。

我认为导出这个组件会很简单,这样我就可以简单地运行npm install MyComponent并开始在一个新项目中使用它。 但是,我发现它并不是那么直截了当。 特别是,我已经阅读了几个小时和几个小时,似乎只是变得更加困惑。

如果我的最终目标是在其包含的项目中继续开发'MyComponent',而在任何其他本地项目中使用'MyComponent',我的选择是什么? 我做的第一件事是将package.jsonmain键更改为/src/components/MyComponent并运行npm pack 这会生成一个tgz文件,我可以通过其绝对文件路径安装在其他项目中。 但是,我发现es6和jsx没有被转换,因此我的客户端项目无法解析MyComponent 然后我使用webpack转换为lib/MyComponent ,但是当我import MyComponent from './path/to/MyComponent-1.0.0.tgz我只在控制台中看到{} (一个空对象)。

寻找我的问题的解决方案出现了许多不同的方法,将NPM,Grunt,Gulp,Babel,Webpack等组合在一起。而且我担心它会花费更多的时间(几天?)才能将其研磨成可以理解的东西。

鉴于我的要求,我可以实现的最简单的解决方案是:1)将我的React组件编译成最简单的导入模块2)将其导入任何本地项目3)继续在原始主机项目中开发包并轻松更改传播到客户项目。

一般来说,如果你要开始创建React组件作为独立的包(这是一个很好的模式,出于你已经提到的所有原因) - 你将需要至少熟悉webpackbabel 这里要学到很多东西,但让我试着指出你正确的方向:

// webpack.config.js

/* eslint-disable */
const path = require('path')
const webpack = require('webpack')

const ENVIRONMENT = process.env.NODE_ENV
const PRODUCTION = ENVIRONMENT === 'production'
const SOURCEMAP = !PRODUCTION || process.env.SOURCEMAP

const library = 'your-lib-name' // << RENAME THIS <<
const filename = PRODUCTION ? `${library}.min.js` : `${library}.js`

const plugins = []

if (PRODUCTION) {
  plugins.push(
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify(ENVIRONMENT),
    }),
    new webpack.optimize.ModuleConcatenationPlugin(),
    new webpack.optimize.UglifyJsPlugin({
      minimize: true,
      output: { comments: false, semicolons: false },
      sourceMap: SOURCEMAP,
    })
  )
}

module.exports = {
  devtool: SOURCEMAP ? 'source-map' : 'none',
  entry:  `${__dirname}/path/to/your/component.js`, // << RENAME THIS <<
  externals: {
    'react': 'react',
    'react-dom': 'react-dom',
  },
  module: {
    loaders: [{
      test:    /\.js$/,
      loader:  'babel-loader',
      exclude: /node_modules/,
    }],
  },
  output: {
    filename,
    library,
    path:           `${__dirname}/lib`,
    libraryTarget:  'umd',
    umdNamedDefine: true,
  },
  plugins,
}

我知道这看起来像一堆 - 但它处理了你想要的大部分。 具体来说:

  1. 如果在构建时指定NODE_ENV=production ,则会对包进行NODE_ENV=production ,并进行其他一些您可能需要的修剪。
  2. 使用此脚本构建将输出一个sourcemap ,您可以使用dev工具在调试器窗口中检查缩小的代码等。
  3. 这标志着externals reactreact-dom - 这意味着它们不会捆绑在一起并打包你的包中。 这是伟大的-因为这意味着你不会得到2+拷贝react的文件大小只是因为你已经import编自己的组件!

但是,要使用它,你现在需要一些package.json爱。

package.json

{
  "name": "Your Name",
  "version": "0.0.1",
  "description": "This is my awesome react package!",
  "main": "path/to/your/component.js",
  "author": "Your Name",
  "license": "MIT",
  "repository": { /* Your Repo Info Here */ },
  "dependencies": {
    "any-packages-you-need-included-in-builds": "^1.0.0"
  },
  "devDependencies": {
    "babel-cli": "^6.22.2",
    "babel-loader": "^7.1.0",
    "babel-preset-es2015": "^6.22.0",
    "babel-preset-react": "^6.22.0",
    "prop-types": "^15.5.10",
    "react-dom": "^15.6.1",
    "webpack": "^3.0.0"
  },
  "scripts": {
    "build": "yarn prebuild && NODE_ENV=production webpack",
    "prebuild": "mkdir -p ./lib && rm -rf ./lib/*"
  }
}

显然,如果你需要它,你可以在这里有更多 - 比如你在转换中使用的其他babel-plugin-*插件,其他包等。但是这个集合将让你的webpack构建运行。 请注意,这里的脚本假设您正在使用yarn - 这样您就可以运行yarn build ,并且您正在使用posix系统,以便mkdir工作。 如果你在窗户上或不使用yarn ,只需相应地更新脚本。

其余的只是学习将包发布到npm或其他包存储库。 首先,这只是将package.jsonversion号设置为新的( npm version )然后发布( npm publish )。 当然,您必须有一个npm帐户 - 并登录( npm login )。

一旦你发布到npm你可以只yarn add your-package-name

但请记住,我们将reactreact-dom标记为external - 因此在使用包中,您需要确保它们可用作window.Reactwindow.ReactDOM - 或者您需要直接包含该组件从node_modules/your-package-name/path/to/your/component.js

你不需要npm pack一个包来使用它。 如果你把你的组件变成一个git repo并把它放在Github上,你可以使用NPM直接从Github安装它,使用npm install alex/mycomponent ,其中alex是你的github用户名, mycomponent是repo名称。 重新运行该命令将从Github重新安装,以防您对repo进行更改。

一旦您对组件感到满意,就可以将其上传到NPM注册表以像其他任何软件包一样npm install namenpm install name )。 首先使用Github使开发更容易一些。

默认情况下,Webpack可能无法从node_modules编译内容。 通常,软件包在发布之前都是预先编译的,但您应该能够配置webpack来构建“打包”组件以及应用程序的其余部分。 也许这会有所帮助: https//stackoverflow.com/a/38008149/7486612

首先查看现有的组件库,例如Material UI 具体检查他们有的npm脚本(参见package.json):

"build:es2015": "cross-env NODE_ENV=production babel ./src --ignore *.spec.js --out-dir ./build",
"build:es2015modules": "cross-env NODE_ENV=production BABEL_ENV=modules babel ./src/index.js --out-file ./build/index.es.js",
"build:copy-files": "babel-node ./scripts/copy-files.js",
"build:umd:dev": "webpack --config scripts/umd.webpack.config.js",
"build:umd:prod": "cross-env NODE_ENV=production webpack --config scripts/umd.webpack.config.js",
"build": "npm run build:es2015 && npm run build:es2015modules && npm run build:copy-files && npm run build:umd:dev && npm run build:umd:prod",

这是非常复杂和高质量的组件库的示例,它确保无论您的构建管道如何,您都可以使用它。

使用webpack设置构建过程可能很麻烦,但是从一开始就不要过于专注于那个过程,并且覆盖对你来说最直接的案例。

在处理组件时,请查看https://storybook.js.org/

为了将反应库推入NPM,您可能需要一些样板来安装和转换许多东西(您仍然可以使用当前的反应模块作为主要来源,只需按照我的答案结尾处的指南,然后你一定会得到所有的想法)

或者您也可以参考我之前对类似问题的回答: 发布到npm的问题

=====

我还成功地将几个反应库推入NPM:

https://www.npmjs.com/~thinhvo0108

=====

你的github存储库的文件夹结构也应该像我的:

https://github.com/thinhvo0108/react-paypal-express-checkout

=====

这里有用的教程:

(样板来源) https://github.com/juliancwirko/react-npm-boilerplate

(作者的文章) http://julian.io/creating-react-npm-packages-with-es2015/

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM