webpack采用esm打包,打包后tree shaking失效,请问如何解决?

作者站长头像
站长
· 阅读数 5

webpack采用esm打包,打包后tree shaking失效,请问如何解决?

我尝试调整webpack配置,如下:

const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');

const isProduction = process.env.NODE_ENV === 'production';
const outputType = process.env.OUTPUT_TYPE;

/** @type {import('webpack').Configuration} */
const config = {
    entry: isProduction ? './components/index.ts' : './demo/index.tsx',

    externals: !isProduction ? {} : {
        react: {
            root: 'React',
            commonjs2: 'react',
            commonjs: 'react',
            amd: 'react',
            module: 'react'
        },
        "react-dom": {
            root: 'ReactDOM',
            commonjs2: 'react-dom',
            commonjs: 'react-dom',
            amd: 'react-dom',
            module: 'react-dom'
        }
    },

    experiments: {
        outputModule: outputType === 'esm'
    },

    mode: isProduction ? 'production' : 'development',
    module: {
        rules: [
            {
                exclude: /node_modules/,
                test: /\.js(x?)$/,
                use: [
                    { loader: 'babel-loader' }
                ]
            },
            {
                exclude: /node_modules/,
                test: /\.ts(x?)$/,
                use: [
                    { loader: 'babel-loader' },
                    { loader: 'ts-loader' }
                ]
            },
            {
                exclude: /.min.css$/,
                test: /\.(sa|sc|c)ss$/,
                use: [
                    { loader: 'style-loader' },
                    {
                        loader: 'css-loader',
                        options: {
                            modules: {
                                mode: 'global'
                            }
                        }
                    },
                    {
                        loader: 'postcss-loader',
                        options: {
                            postcssOptions: {
                                plugins: [
                                    'postcss-preset-env'
                                ]
                            }
                        }
                    },
                    { loader: 'sass-loader' }
                ],
            }
        ]
    },

    output: outputType === 'esm' ? {
        chunkFormat: 'module',
        clean: true,
        filename: '[name].esm.js',
        library: {
            type: 'module'
        },
        path: path.resolve(__dirname, '../es')
    } : {
        clean: true,
        filename: '[name].js',
        library: {
            export: 'default',
            name: 'rollup-test',
            type: 'umd'
        },
        path: path.resolve(__dirname, '../lib')
    },

    plugins: [
        ...(!isProduction ? [new HtmlWebpackPlugin({
            filename: 'index.html',
            template: path.resolve(__dirname, '../demo/index.html'),
            title: 'rollup-test'
        })] : [])
    ],

    resolve: {
        extensions: ['.ts', '.tsx', '.js', 'jsx', '.json']
    },
};

module.exports = config;

然后package.json如下:

...
  "main": "lib/main.js",
  "module": "es/main.esm.js",
  "types": "types/index.d.ts",
  "sideEffects": false,
  "scripts": {
    "build": "npm run generate:esm & npm run generate:umd",
    "generate:esm": "cross-env BABEL_ENV=esm NODE_ENV=production OUTPUT_TYPE=esm webpack --config ./config/webpack.config.js",
    "generate:umd": "cross-env BABEL_ENV=build NODE_ENV=production OUTPUT_TYPE=umd webpack --config ./config/webpack.config.js",
  }
...

导出的esm文件也正常,如下

/*! For license information please see main.esm.js.LICENSE.txt */
import*as r from"react";export const id=179;export const ids=[179];export const modules={564:(r,e,t)=>{t.d(e,{bZ:()=>n,zx:()=>s,ZP:()=>a});var o=t(893);const n=function(r){var e=r.children;return(0,o.jsx)("div",{className:"alert-component",children:e})};t(846);const s=function(r){var e=r.children;return(0,o.jsx)("div",{className:"button-component",children:e})},a={Alert:n,Button:s}},251:(r,e,t)=>{var o=t(846),n=Symbol.for("react.element"),s=(Symbol.for("react.fragment"),Object.prototype.hasOwnProperty),a=o.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,c={key:!0,ref:!0,__self:!0,__source:!0};e.jsx=function(r,e,t){var o,i={},l=null,f=null;for(o in void 0!==t&&(l=""+t),void 0!==e.key&&(l=""+e.key),void 0!==e.ref&&(f=e.ref),e)s.call(e,o)&&!c.hasOwnProperty(o)&&(i[o]=e[o]);if(r&&r.defaultProps)for(o in e=r.defaultProps)void 0===i[o]&&(i[o]=e[o]);return{$$typeof:n,type:r,key:l,ref:f,props:i,_owner:a.current}}},893:(r,e,t)=>{r.exports=t(251)},846:e=>{e.exports=r}};import e from"./manifest.esm.js";import*as t from"./main.esm.js";e.C(t);var o=(564,e(e.s=564)),n=o.bZ,s=o.zx,a=o.ZP;export{n as Alert,s as Button,a as default};

但是通过npm linknpm run build发现tree shaking失效,无论是否使用,所有文件都构建了

回复
1个回答
avatar
test
2024-06-23

已换Rollup,webpack打包esm存在副作用,如果是开发应用,无所谓,开发库目前无解,建议换Rollup

answer image

看了好几天的文章,最终总结划重点

answer image

回复
likes
适合作为回答的
  • 经过验证的有效解决办法
  • 自己的经验指引,对解决问题有帮助
  • 遵循 Markdown 语法排版,代码语义正确
不该作为回答的
  • 询问内容细节或回复楼层
  • 与题目无关的内容
  • “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容