美文网首页
webpack5 创建react-library

webpack5 创建react-library

作者: 申_9a33 | 来源:发表于2022-02-24 15:45 被阅读0次

    1.拉取一份 react创建的工程 地址


    2. 开发 思路

    • 分两个文件夹
    • dev 开启一个react开发项目
    • src 为具体库的实现代码
    • 然webpack配置一个正常的react项目,入口设置为dev下面的index
    • 这样启动这个webpack,就可以在线开发src下面的库了

    2.1 以实现一个react弹窗组件为例,先写一个弹窗组件

    // src\index.tsx
    
    import React, { Component } from 'react';
    import { createPortal } from 'react-dom';
    import './index.scss';
    
    export interface IDialogProps{
      hideDialog:Function
    }
    export default class Dialog extends Component<IDialogProps> {
      node:HTMLElement;
    
      constructor(props:IDialogProps) {
        super(props);
    
        this.node = document.createElement('div');
        this.node.classList.add('dialog');
      }
    
      componentDidMount() {
        document.body.appendChild(this.node);
      }
    
      componentWillUnmount() {
        document.body.removeChild(this.node);
      }
    
      render() {
        const { hideDialog, children } = this.props;
        return createPortal(
          <div className="dialog-model">
            {children}
            {typeof hideDialog === 'function' && (
            <button onClick={() => hideDialog()} type="button">关闭窗口</button>
            )}
          </div>, this.node,
        );
      }
    }
    
    

    2.2 在example开启react开发项目,并且使用src导出的Dialog

    // example\index.tsx
    
    import React, {  useState } from 'react'
    import ReactDOM from 'react-dom';
    
    import Diallog from '../src/index'
    
    function App(){
      const [isShowDialog,setIsShowDialog] = useState(false)
      return (
        <div>
          <h3>DialogPage</h3>
          <button onClick={() => setIsShowDialog(true)}>
              toggle
          </button>
          {isShowDialog && <Diallog children="hello" hideDialog={() => setIsShowDialog(false)} />}
        </div>
        )
    }
    
    
    ReactDOM.render(<App />,document.getElementById('root'));
    

    2.3 配置 example 的webpack

    const path = require('path');
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    
    module.exports = {
        entry: './dev/index.tsx',
        output: {
          filename: '[name].bundle.js',
          path: path.resolve(__dirname, 'build'),
        },
        mode: 'development',
        devtool: 'inline-source-map',
        devServer: {
            contentBase: './build',
            // 启动gzip 压缩0
            compress: true,
            // 端口号
            port: 8080,
            open: true,
            hot: true,
        },
        plugins: [
          new HtmlWebpackPlugin({ template: './index.html' }),
        ],
        module: {
            rules: [
                {
                  test: /\.html$/i,
                  // 处理html文件的img图片(负责引入img,从而能被url-loader进行处理)
                  loader: 'html-loader',
                },
                {
                  test: /\.(ts|js)x?$/,
                  exclude: /node_modules/,
                  loader: 'babel-loader',
                },
                {
                  test: /\.(png|svg|jpg|jpeg|gif)$/i,
                  type: 'asset/resource',
                  generator: {
                    filename: 'static/images/[hash][ext][query]',
                  },
                },
                {
                  test: /\.(woff|woff2|eot|ttf|otf)$/i,
                  type: 'asset/resource',
                  generator: {
                    filename: 'static/font/[hash][ext][query]',
                  },
                },
                {
                    test: /\.((c|sa|sc)ss)$/i,
                    use: [
                        "style-loader",
                        "css-loader",
                        'sass-loader'
                    ]
                }
            ]
        },
        optimization: {
          splitChunks: {
            chunks: 'all',
          },
        },
        resolve: {
          // 配置省略文件路径的后缀名
          extensions: ['.tsx', '.ts', '.js'],
        },
    }
    

    2.4 最后 npm run start 就可以愉快的开发自己的库了


    3.打包思路

    • 开启一个webpack,配置为library
    • 排除用到的 react
    • 去掉corejs

    3.1 配置一个生产环境的webpack

    const MiniCssExtractPlugin = require("mini-css-extract-plugin")
    const { CleanWebpackPlugin } = require('clean-webpack-plugin');
    const path = require('path');
    
    module.exports = {
        entry: './src/index.tsx',
        mode: 'production',
        devtool: 'source-map',
        output: {
          filename: 'index.js',
          path: path.resolve(__dirname, 'dist'),
          library:'react-dialog',
          libraryTarget: 'umd'
        },
        plugins: [
            new CleanWebpackPlugin(),
            new MiniCssExtractPlugin({
                filename: 'style.css',
                chunkFilename: '[id].css',
            }),
        ],
        module: {
            rules: [
                {
                  test: /\.(ts|js)x?$/,
                  exclude: /node_modules/,
                  loader: 'babel-loader',
                },
                {
                  test: /\.(png|svg|jpg|jpeg|gif)$/i,
                  type: 'asset/resource',
                  generator: {
                    filename: 'static/images/[hash][ext][query]',
                  },
                },
                {
                  test: /\.(woff|woff2|eot|ttf|otf)$/i,
                  type: 'asset/resource',
                  generator: {
                    filename: 'static/font/[hash][ext][query]',
                  },
                },
                {
                    test: /\.((c|sa|sc)ss)$/i,
                    use: [
                        {
                            loader: MiniCssExtractPlugin.loader,
                        },
                        // 将css文件变成commonjs模块加载js中,里面内容是样式字符串
                        {
                            loader: 'css-loader',
                            options: {
                                importLoaders: 2,
                            }
                        },
                        'postcss-loader',
                        'sass-loader'
                    ],
                },
            ]
        },
        resolve: {
          // 配置省略文件路径的后缀名
          extensions: ['.tsx', '.ts', '.js'],
        },
        externals:{
          react:'react',
          'react-dom':'react-dom'
        }
    }
    
    
    • library:'react-dialog'是库名称,libraryTarget: 'umd'编译库的目标,umd 代表ES2015,CommonJS可以使用
    • externals,用户会导入的库,这里不用引入,减少打包体积

    3.2 去掉corejs,这里不引入减少打包体积,放给用户去引入

    // .babelrc
    
    {
        "presets": [
            "@babel/env",
            "@babel/preset-react",
            "@babel/preset-typescript"
        ],
        "plugins": [
            "@babel/plugin-proposal-class-properties"
        ]
    }
    

    3.3 运行npm run build,会打包我们的组件库


    4. 推送到npm

    4.1 修改package.json

      "name": "@shen9401/react-dialog",
      "main": "dist/index.js",
      "module": "dist/index.js",
      "style": "dist/style.css",
      "files": [
        "dist"
      ],
    
    • main node和浏览器所需要的文件 ; module 是node和浏览器ES模块需要的文件
    • "sideEffects": false ,会忽略css

    4.2 登录到自己的npm账户

    npm adduser --registry=https://registry.npmjs.org/
    
    • 会提示输入用户名,密码,邮箱,以及注册邮箱的验证码

    4.3 使用 nrm use npm 切换到npm 源

    4.4 npm publish --access public 发布公共包


    5.新建一个react项目

    5.1 执行 npm i @shen9401/react-dialog 按照包

    5.2 引入并使用

    import Diallog from '@shen9401/react-dialog'
    import '@shen9401/react-dialog/dist/style.css'
    function App() {
      const [isShowDialog,setIsShowDialog] = useState(false)
      return (
        <div className="App">
          <button onClick={() => setIsShowDialog(true)}>
              toggle
          </button>
          {isShowDialog && <Diallog children="hello" hideDialog={() => setIsShowDialog(false)} />}
        </div>
      );
    }
    

    6. 合并js和css, 修改webpack 配置,避免引入组件之后还要引入样式

                {
                    test: /\.((c|sa|sc)ss)$/i,
                    use: [
                      "style-loader",
                        // 将css文件变成commonjs模块加载js中,里面内容是样式字符串
                        {
                            loader: 'css-loader',
                            options: {
                                importLoaders: 2,
                            }
                        },
                        'postcss-loader',
                        'sass-loader'
                    ],
                },
    
    • 去掉 MiniCssExtractPlugin,改用style-loader

    源码

    相关文章

      网友评论

          本文标题:webpack5 创建react-library

          本文链接:https://www.haomeiwen.com/subject/jnoolrtx.html