我正在创建一个可共享的React组件库。
该库包含许多组件,但最终用户可能只需要使用其中一些组件。
当您将代码与Webpack(或Parcel或Rollup)捆绑在一起时,它将使用所有代码创建一个文件。
出于性能原因,除非实际使用该代码,否则我不希望浏览器下载所有这些代码。 我是否认为我不应该捆绑组件是正确的吗?捆绑产品应由组件的使用者承担吗? 我是否还要将其他东西留给组件的使用者?我只需要转换JSX就可以了吗?
如果同一仓库包含很多不同的组件,那么main.js应该是什么?
答案 0 :(得分:16)
这是一个非常漫长的答案,因为该问题值得一个非常漫长而详尽的答案,因为“最佳实践”的方式要比仅几行回答更为复杂。
在那段时间里,我将自己的内部图书馆维持了3.5年以上,我以两种方式解决我认为应该将图书馆捆绑在一起的问题,取舍取决于您的图书馆的规模,而我们本人亲自编写两种方式取悦消费者的两个子集。
方法1:创建一个index.ts文件,将要公开的所有内容导出,并将该文件的目标汇总作为输入。将整个库捆绑到单个index.js文件和index.css文件中;用外部依赖项从使用者项目继承来避免重复的库代码。 (要点包含在示例配置的底部)
import { Foo, Bar } from "library"
导入所有内容方法2:适用于高级用户:为每个导出创建一个新文件,并使用rollup-plugin-multi-input和“ preserveModules:true”选项,具体取决于您所使用的CSS系统的方式确保您的css不会合并到单个文件中,但是在汇总后每个css文件的require(“。css”)语句仍留在输出文件中并且该css文件存在。
next-transpile-modules
npm软件包完成的。import { Foo,Bar } from "library"
,然后通过babel将其转换为... import { Foo } from "library/dist/export/foo"
import { Bar } from "library/dist/export/bar"
我们有多个汇总配置,实际上我们同时使用这两种方法。因此,对于那些不关心摇树的图书馆用户,只需"Foo from "library"
并导入单个css文件即可;对于关心树木摇晃并且仅使用关键CSS的图书馆用户,他们只需打开我们的babel插件即可。
最佳实践汇总指南:
是否使用打字稿,是否始终使用"rollup-plugin-babel": "5.0.0-alpha.1"
构建
确保您的.babelrc看起来像这样。
{
"presets": [
["@babel/preset-env", {
"targets": {"chrome": "58", "ie": "11"},
"useBuiltIns": false
}],
"@babel/preset-react",
"@babel/preset-typescript"
],
"plugins": [
["@babel/plugin-transform-runtime", {
"absoluteRuntime": false,
"corejs": false,
"helpers": true,
"regenerator": true,
"useESModules": false,
"version": "^7.8.3"
}],
"@babel/plugin-proposal-class-properties",
"@babel/plugin-transform-classes",
["@babel/plugin-proposal-optional-chaining", {
"loose": true
}]
]
}
并且汇总中的babel插件看起来像这样...
babel({
babelHelpers: "runtime",
extensions,
include: ["src/**/*"],
exclude: "node_modules/**",
babelrc: true
}),
您的package.json看起来像ATLEAST:
"dependencies": {
"@babel/runtime": "^7.8.3",
"react": "^16.10.2",
"react-dom": "^16.10.2",
"regenerator-runtime": "^0.13.3"
},
"peerDependencies": {
"react": "^16.12.0",
"react-dom": "^16.12.0",
}
最后,您的外部汇总看起来像这样的ATLEAST。
const makeExternalPredicate = externalArr => {
if (externalArr.length === 0) return () => false;
return id => new RegExp(`^(${externalArr.join('|')})($|/)`).test(id);
};
//... rest of rollup config above external.
external: makeExternalPredicate(Object.keys(pkg.peerDependencies || {}).concat(Object.keys(pkg.dependencies || {}))),
// rest of rollup config below external.
为什么?
最后,这是一个示例单个index.js文件输出汇总配置文件的要点。 https://gist.github.com/ShanonJackson/deb65ebf5b2094b3eac6141b9c25a0e3 目标src / export / index.ts看起来像这样...
export { Button } from "../components/Button/Button";
export * from "../components/Button/Button.styles";
export { Checkbox } from "../components/Checkbox/Checkbox";
export * from "../components/Checkbox/Checkbox.styles";
export { DatePicker } from "../components/DateTimePicker/DatePicker/DatePicker";
export { TimePicker } from "../components/DateTimePicker/TimePicker/TimePicker";
export { DayPicker } from "../components/DayPicker/DayPicker";
// etc etc etc
如果您在使用babel,汇总时遇到任何问题,或者对捆绑/库有任何疑问,请与我联系。
答案 1 :(得分:3)
将代码与Webpack(或Parcel或Rollup)捆绑在一起时,它将使用所有代码创建一个文件。
出于性能方面的考虑,我不希望浏览器下载所有代码,除非实际使用了这些代码
可能为每个组件生成了单独的文件。 Webpack通过定义多个条目和输出而具有这种能力。假设您具有以下项目结构
- my-cool-react-components
- src // Folder contains all source code
- index.js
- componentA.js
- componentB.js
- ...
- lib // Folder is generated when build
- index.js // Contains components all together
- componentA.js
- componentB.js
- ...
Webpack文件看起来像这样
const path = require('path');
module.exports = {
entry: {
index: './src/index.js',
componentA: './src/componentA.js',
componentB: './src/componentB.js',
},
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'lib'),
},
};
有关“代码拆分”的更多信息,请参见Webpack docs
如果同一仓库包含很多不同的组件,那么main.js应该是什么?
package.json
文件中有一个名为main
的字段,最好根据上面的项目结构放置其值lib/index.js
。并且在index.js
文件中导出了所有组件。如果消费者想使用单个组件,只需简单地做到
const componentX = require('my-cool-react-components/lib/componentX');
我是否认为我不应该捆绑组件?捆绑产品应由组件的使用者承担吗?我是否还要将其他东西留给组件的使用者?我只需要转换JSX就可以了吗?
好吧,这取决于您。我发现有些React库是以原始方式发布的,其他的则是以捆绑方式发布的。如果需要一些构建过程,请对其进行定义并导出捆绑的版本。
希望,您的所有问题都得到了回答:)
答案 2 :(得分:2)
您可以像lodash一样拆分其组件。
您可能拥有的是单独的组件,可以允许它们分别导入或通过主要组件导入。
然后,消费者可以导入整个包裹
foo=$(for i in {0..7}; do echo -n "uops_dispatched_port.port_$i|p$i,"; done)
export FOO=${foo%,}
或其各个部分
import {MyComponent} from 'my-components';
消费者将基于他们导入的组件创建自己的捆绑软件。那应该可以防止下载整个软件包。
答案 3 :(得分:1)
您应该看看Bit,我认为这是共享,重用和可视化组件的好方法。
这很容易设置。您可以使用以下方法安装位库或仅安装组件:
npm i @bit/bit.your-library.components.buttons
然后,您可以使用以下命令将组件导入应用程序中:
import Button3 from '@bit/bit.your-library.components.buttons';
好处是您不必担心配置Webpack和所有爵士乐。 Bit甚至支持组件的版本控制。 example显示了标题列表反应组件,因此您可以查看它是否满足您的要求
答案 4 :(得分:0)
webpack中有一个配置可以创建块文件。首先,它将主捆绑包分成多个块,并在需要时加载它。如果您的项目具有结构良好的模块,则不会加载任何不需要的代码。