MRCXX / BLOG

MIT License
1 stars 0 forks source link

关于在create-react-app中打包/导出/发布组件 #6

Open MRCXX opened 4 years ago

MRCXX commented 4 years ago

这段是废话

事情是这样的, 大概上周有个需求需要做一个“人员选择器”组件, 这不简单吗, 我之前花了两天时间在 VUE 上实现过一次, 这次用 React 来实现应该会更快, 重点是有多个项目都要用到这个选择器, 然后这里就埋下了一个伏笔.

我一如既往的用 create-react-app(简称cra) 来初始化应用, 两天过去, 我开发到了90%, 考虑到多个项目用到, 那我肯定需要把组件打包并发布(内部提交到gitlab). 但是 cra 打包出来的是项目, 一个完整的项目, 包含 html 的项目, 但我只需要把组件编译成 js

首先在上官网查查, 结果是并不支持 https://create-react-app.dev/docs/deployment/#publishing-components-to-npm

image

然后我开始google查“create-react-app 打包 组件”, “create-react-app build component”, 只找到一些基于 babel 打包js文件的文章. 由于我用到了typescript, 所以肯定需要 webpack 或者 rollup 来打包.

这个时候慌了, 因为快下班, 晚会时答应了明天要把组件交给同事对接, 我只有一个晚上来处理, 最多第二天的下午.

决定方案

Rollup

就不介绍Rollup了, 他和webpack类似, 总结一句就是开发组件/插件用roolup, 开发项目用webpack, 配置都基于typescript-library-starter. ps: 其实rollup截止目前已经更新到版本2.x, 但是我们这个demo还是用的0.x的版本, 虽然也能用, 但是可能会有一些插件会不支持, 后续我有空更新一下.

// package.json
"scripts": {
   ...
    "biu": "tsc --module commonjs && rollup -c rollup.config.ts && typedoc --out docs --target es6 --theme minimal --mode file src" // 添加一个编译命令
  },
"devDependencies": {
    ...
    "rollup": "^2.3.0",
    "rollup-plugin-commonjs": "^10.1.0",
    "rollup-plugin-json": "^4.0.0",
    "rollup-plugin-node-resolve": "^5.2.0",
    "rollup-plugin-postcss": "^2.5.0",
    "rollup-plugin-sourcemaps": "^0.5.0",
    "rollup-plugin-svg": "^2.0.0",
    "rollup-plugin-typescript2": "^0.27.0",
    "typedoc": "^0.17.3"
  }
// 从https://github.com/alexjoverm/typescript-library-starter项目拷贝过来
// rollup.config.ts
// 当然要改一下入口等配置
import resolve from 'rollup-plugin-node-resolve'
import commonjs from 'rollup-plugin-commonjs'
import sourceMaps from 'rollup-plugin-sourcemaps'
import camelCase from 'lodash.camelcase'
import typescript from 'rollup-plugin-typescript2'
import json from 'rollup-plugin-json'
import postcss from 'rollup-plugin-postcss'
import svg from 'rollup-plugin-svg'
// import babel from 'rollup-plugin-babel' // 可以引入babel, 具体请看文档

const pkg = require('./package.json')
const libraryName = 'xxx'

export default {
  input: `src/xxx.tsx`, // 入口文件
  output: [
    { file: pkg.main, name: camelCase('App'), format: 'umd', sourcemap: true },
    { file: pkg.module, format: 'es', sourcemap: true }
  ],
  external: ['react', 'reactDom', 'lodash', 'antd-mobile', 'axios'], // 不打包的依赖
  watch: {
    include: 'src/**'
  },
  plugins: [
    json(),
    typescript({ useTsconfigDeclarationDir: true }),
    commonjs(),
    resolve(),
    sourceMaps(),
    svg({
      base64: true
    }),
    // image(),
    postcss({
      plugins: []
    })
    // babel()
  ]
}
// tsconfig.json
// 官方方案提供的配置
// 如果rollup是低版本, resolveJsonModule要设置为false, 不然会报错
{
  "compilerOptions": {
    "target": "es5",
    "sourceMap": true,
    "declaration": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "declarationDir": "dist/types",
    "outDir": "dist/lib",
    "typeRoots": ["node_modules/@types"],
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": false, // 要改成false
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react"
  },
  "include": ["src"]
}

入口文件也需要修改, 因为我们需要export组件才能在别的地方引入, 我在App.tsx中export(在其他地方也是可以的), 这里随便举个例子

// App.tsx
import React from 'react'
import './App.scss'

export const Debug = () => {
  return (
    <div>123</div>
  )
}

到时候我们用的时候就是

//debug.tsx
import React from 'react'
import { Debug } from 'component_name'

export const Debug2 = (setting) => {
  return (
    <Debug />
  )
}

我出现过的问题

总结

最后

学到的

MRCXX commented 4 years ago

本来打算把文章发在juejin, 发现需要验证手机号码, 所以算了, 就这样了吧