vite和webpack打包lib库细节

142 阅读2分钟

概述

常见的组件库,业务工程项目,都会用到各式各样的npm包,打包的格式也很多元,比如umd,cjs,es等,不同打包格式,适合不同环境不同导入方式,以下是关于现在主流webpack和vite这两个环境打包的配置信息,如果自己要写npm包给别人用,打包配置必不可少。

webpack配置

webpack.config.js配置如下, 依赖如下:

  • webpack
  • webpack-cli
  • vue-loader
  • clean-webpack-plugin
  • ts-loader
  • style-loader
  • css-loader
  • postcss-loader
  • sass-loader/less-loader(根据情况定)

如下配置会将所有资源输出到一份文件中,如果需要将资源分块输出,可以参考webpack分解到不同文件配置

const path = require('path');
const { VueLoaderPlugin } = require('vue-loader');
// const { CleanWebpackPlugin } = require('clean-webpack-plugin');

//注意:wenbapack单入口输出多文件,需要数组形式,CleanWebpackPlugin关闭,不然会覆盖其他生成的文件
const baseConfig = {
  mode: 'production',
  entry: path.resolve(__dirname, './src/index.js'),
  resolve: {
    extensions: ['.ts', '.js', '.vue', '.json'],
  },
  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader',
        options: {
          reactivityTransform: true // 可选:启用 Vue 3 响应性语法糖
        }
      },
      {
        test: /\.ts$/,
        loader: 'ts-loader',
        options: {
          appendTsSuffixTo: [/\.vue$/],
          transpileOnly: true,
          // 使用项目中的 tsconfig.json
          configFile: path.resolve(__dirname, 'tsconfig.json')
        },
        exclude: /node_modules/
      },
      {
        test: /\.css$/,
        use: [
         'style-loader',
          'css-loader',
          'postcss-loader'
        ]
      },
      {
        test: /\.scss$/,
        use: [
         'style-loader',
          'css-loader',
          'postcss-loader',
          'sass-loader'
        ]
      },
      {
        test: /\.(png|jpe?g|gif|svg|webp)$/,
        type: 'asset/inline',
      },
      {
        test: /\.(woff2?|eot|ttf|otf)$/,
        type: 'asset/inline',
      }
    ]
  },
  plugins: [
    new VueLoaderPlugin(),
    // new CleanWebpackPlugin(),
  ],
  optimization: {
    minimize: true,
    splitChunks: false // 禁用代码分割,因为我们打包的是库
  },
  performance: {
    hints: false,
    maxEntrypointSize: 512000,
    maxAssetSize: 512000
  }
};
module.exports = (env, argv) => {
  return [
    {
      ...baseConfig,
      output: {
        path: path.resolve(__dirname, './dist'),
        filename: 'index.umd.js',
        library: {
          name: ['myNamespace','MyComponent'],
          type: 'umd',
        },
        umdNamedDefine: false,
  
      },
    },
    {
      ...baseConfig,
      experiments: {
        outputModule: true // 启用实验性 ESM 输出支持
          },
      output: {
        path: path.resolve(__dirname, './dist'),
        filename: 'index.es.js',
  
        library: {
          type: 'module',
        },
        umdNamedDefine: false,
  
      },
    },
    {
      ...baseConfig,
      output: {
        path: path.resolve(__dirname, './dist'),
        filename: 'index.cjs',
        library: {
          name: ['myNamespace','MyComponent'],
          type: 'commonjs',
        },
        umdNamedDefine: false,
  
      },
    },
  ]
};

vite配置

vite.config.js 依赖如下:

  • vite-plugin-css-injected-by-js(将所有资源内聚到js中)
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import cssInjectedByJsPlugin from 'vite-plugin-css-injected-by-js'
// https://vite.dev/config/
export default defineConfig({
 plugins: [vue(),
   cssInjectedByJsPlugin() // 强制 CSS 内联到 JS
],
 build: {
   minify: true, 
   emptyOutDir: true ,
   cssCodeSplit: false, //禁止代码分割  
   assetsInlineLimit: 100 * 1024 * 1024, // 100MB
   lib: {
     entry: './src/index.js', // 组件入口文件
     name: `myNamespace.MyComponent`,     // 全局变量名(与平台约定)
     formats: ['umd',"es","cjs"],        // 必须使用UMD格式
     fileName: 'index' // 输出文件名
   },
   rollupOptions: {
    
     output: {
       manualChunks: undefined, // 强制内联动态导入
       inlineDynamicImports: true,
       entryFileNames:'[name].[format].js'
     }
   }
 }
})

最后执行输入如下

  • vite

image.png

  • webpack

image.png

外部使用

第三方使用我们上传的组件或者包的时候,我们包的package.json中需要配置exports字段,这样外面通过require和import就可以区分出使用哪个入口包了,做到兼容

image.png