侧边栏壁纸
博主头像
恪晨博主等级

前端程序员

  • 累计撰写 141 篇文章
  • 累计创建 41 个标签
  • 累计收到 17 条评论

目 录CONTENT

文章目录

使用webpack构建React组件发布至npm实战

恪晨
2023-09-19 / 0 评论 / 0 点赞 / 119 阅读 / 1,548 字 / 正在检测是否收录...

初始化项目

  使用webpack4.X版本结合React实现对组件的封装并发不到npm官方仓库进行使用

新建package.json

其中有涉及到对css样式文件进行构建的依赖包,可根据实际场景进行选择性安装

{
  "name": "kechenexample",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "webpack-dev-server --mode development --config webpack.config.dev.js",
    "build": "webpack --config webpack.config.prod.js",
    "update": "concurrently \"npm version patch\" \"npm run build\""
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "antd": "^4.24.14",
    "react": "^16.14.0",
    "react-dom": "^16.14.0"
  },
  "devDependencies": {
    "@babel/core": "^7.22.17",
    "@babel/plugin-proposal-class-properties": "^7.12.13",
    "@babel/plugin-transform-runtime": "^7.22.15",
    "@babel/preset-env": "^7.22.15",
    "@babel/preset-react": "^7.12.10",
    "@babel/runtime": "^7.22.15",
    "@babel/runtime-corejs3": "^7.22.15",
    "autoprefixer": "^10.4.15",
    "babel-loader": "^8.1.3",
    "babel-plugin-import": "^1.13.8",
    "concurrently": "^8.2.1",
    "copy-webpack-plugin": "^5.1.2",
    "css-loader": "^5.2.7",
    "html-webpack-plugin": "^4.5.0",
    "postcss-loader": "^4.0.0",
    "style-loader": "^2.0.0",
    "url-loader": "^3.0.0",
    "webpack": "^4.43.0",
    "webpack-cli": "^3.3.12",
    "webpack-dev-server": "^3.2"
  }
}

新建.babelrc

配置预处理以及相关的插件,配置antd按需加载

{
    "presets": ["@babel/preset-react", "@babel/preset-env"],
    "plugins":[[
        "import",{
            "libraryName":"antd",
            "libraryDirectory":"es",
            "style":"css"
        }],
        [
            "@babel/plugin-transform-runtime",
            {
                "corejs": 3
            },
            "@babel/plugin-proposal-class-properties"
        ]
    ]
}

新建src/index.js

import React from "react";
import {Card} from 'antd';
import 'antd/dist/antd.css';
import './index.css';
const MyComponent = () => {
    return <div>
        <p>hello,我 是title</p>
        <Card title="我是title">我是card</Card>
    </div>
};

export default MyComponent;

新建example/index.js与index.html

  • index.js
import React from 'react';
import { render } from 'react-dom';
import MyComponent from '../src';
const App = () => (
    <MyComponent>hello</MyComponent>
);
render(<App />, document.getElementById("root"));
  • index.html
<html>
<head>
  <title>My Component Demo</title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
</head>
<body>
<noscript>
  You need to enable JavaScript to run this app.
</noscript>
<div id="root"></div>
</body>
</html>

新建webpack.common.js

将要构建的文件构建成umd的库文件,构建目的文件夹为dist,构建出的文件名称根据实际入口文件进行自动生成。

const path = require('path');

module.exports = {
    output: {
        filename: '[name].js',
        path: path.resolve(__dirname, 'dist'),
        libraryTarget: 'umd',
    },
    module: {
        rules: [
            {
                test: /\.(js|jsx)$/,
                use: {loader: 'babel-loader'},
                // 配置都加到了.babelrc
                exclude: /node_modules/
                //排除 node_modules 目录,
            },
            {
                test: /\.css$/,
                use: [
                    'style-loader',
                    'css-loader',
                    {
                        loader: 'postcss-loader',
                        options: {
                            postcssOptions: {
                                plugins: [
                                    require('autoprefixer')
                                ]
                            }
                        }
                    }
                ]
            },
            {
                test: /\.(png|jpg|gif|jpeg|webp|svg|eot|ttf|woff|woff2)$/,
                exclude: /node_modules/,
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            // limit: 102400, //低于10k的资源将会被转化成base64
                            esModule: false // 设置为 false,否则,<img src={require('XXX.jpg')} /> 会出现 <img src=[Module Object] />
                        }
                    }
                ],
            }
        ]
    },
    resolve: {
        extensions: [".js", ".jsx"]
    }
}

新建webpack.dev.js

  本地开发需要使用devserver,并且入口文件需要配置多文件,将demo的入口也进行配置,同时也要使用HtmlWebpackPlugin将html进行构建,才能运行demo。

const commonConfig = require('./webpack.common');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');

module.exports = {
    ...commonConfig,
    entry: {
        index: './src/index.js',
        demo: './example/index.js'
    },
    mode: "development",
    plugins: [
        new HtmlWebpackPlugin({
            template: path.join(__dirname, "./example/index.html"),
            filename: 'index.html', //打包后的文件名
            hash: true //是否加上hash,默认是 false
        })
    ],
    devServer: {
        port: '3001', //默认是8080
        open: true, //自动打开浏览器
        hot: true, //热更新
    }
}

新建webpack.prod.js

  最后要发布到npm的文件只需要src下面的文件即可,所以入口处只需要配置src下面的index.js即可,输出文件名默认设置为index.js,后续在使用npm包的时候方便引入。externals配置项可以将不需要构建的包进行排除,copy-webpack-plugin将package.json复制到跟构建目标文件夹,便于npm发布时使用。

const path = require("path");
const CopyPlugin = require("copy-webpack-plugin");
const commonConfig = require('./webpack.common');

module.exports = {
    ...commonConfig,
    entry: './src/index.js',
    output: {
        filename: 'index.js',
        path: path.resolve(__dirname, 'dist'),
        libraryTarget: 'umd',
    },
    mode: "production",
    externals: {
        react: 'React'
    },
    plugins: [
        new CopyPlugin([
            {
                from: 'package.json',
                to: ".",
            }]
        ),
    ],
    performance: {
        // 禁用 size 警告
        hints: false,
        // 入口起点的最大体积
        maxEntrypointSize: 50000000,
        // 生成文件的最大体积
        maxAssetSize: 30000000,
        // 只给出 js 文件的性能提示
        assetFilter: function (assetFilename) {
            return assetFilename.endsWith('.js');
        },
    }
}

构建发布

  在package.json中已经配置了publish命令,可以通过npm run update进行构建与自动迭代版本号,默认使用了的每执行一次自动增加一个patch版本号,可以根据自己的使用进行进行修改。
  发布时需要先登陆npm,进入dist文件夹后进行发布。

注意事项

  • 不支持ts语法,需要使用ts语法的可以自己增加ts-loader等ts的配置;
  • 发布时,如果只执行npm run publish命令则所在文件夹必须是dist文件夹,或者使用npm run publish dist的方式对执行文件夹进行发布;
  • 项目示例中使用的是webpack4.x版本,用到的copy-webpack-plugin插件要注意版本不能太高,截止20230921时,copy-webpack-plugin的版本最新为11.x,在webpack4.x中应该使用5.x版本;
  • webapck内部的配置方式有很多种,使用相关的插件也可以根据文档自行摸索;
0

评论区