【问题标题】:Not able to tree shake lodash in a Webpack, TypeScript project无法在 Webpack、TypeScript 项目中摇树 lodash
【发布时间】:2018-02-28 19:01:04
【问题描述】:

我的目标是在我的webpack.prod.js 中摇树lodash(以及其他)。这是我的配置文件。为了完整起见,我还将包括 webpack.dev.js、webpack.common.js、tsconfig.json 和 package.json:

webpack.common.js:

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

module.exports = {
    module: {
        rules: [
            {
                test: /\.(png|svg|jpg|gif|obj)$/,
                use: [
                    'file-loader'
                ]
            },
            {
                test: /\.glsl$/,
                loader: 'webpack-glsl-loader'
            },
            {
                test: /\.tsx?$/,
                use: 'ts-loader',
                exclude: /node_modules/
            },
            {
                test: /\.ts$/,
                enforce: 'pre',
                loader: 'tslint-loader',
                options: { failOnHint: true }
            }
        ]
    },
    resolve: {
        extensions: [".tsx", ".ts", ".js"]
    },
    entry: {
        app: './src/index.ts'
    },
    plugins: [
        new CleanWebpackPlugin(['dist']),
        new HtmlWebpackPlugin({
            title: 'Production'
        })
    ],
    output: {
        filename: '[name].bundle.js',
        path: path.resolve(__dirname, 'dist')
    }
};

webpack.dev.js:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const JarvisPlugin = require("webpack-jarvis");
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

module.exports = {
    module: {
        rules: [
            {
                test: /\.(png|svg|jpg|gif|obj)$/,
                use: [
                    'file-loader'
                ]
            },
            {
                test: /\.glsl$/,
                loader: 'webpack-glsl-loader'
            },
            {
                test: /\.tsx?$/,
                use: 'ts-loader',
                exclude: /node_modules/
            },
            {
                test: /\.ts$/,
                enforce: 'pre',
                loader: 'tslint-loader',
                options: { failOnHint: true }
            }
        ]
    },
    resolve: {
        extensions: [".tsx", ".ts", ".js"]
    },
    entry: {
        app: './src/index.ts'
    },
    devtool: 'inline-source-map',
    devServer: {
        contentBase: './dist'
    },
    plugins: [
        new HtmlWebpackPlugin({ title: 'urknall-core dev' }),
        new BundleAnalyzerPlugin({ analyzerPort: 8888 }),
        new JarvisPlugin({ port: 1337 }),
    ],
    output: {
        filename: '[name].bundle.js',
        publicPath: '/'
    }
};

webpack.prod.js:

const webpack = require('webpack');
const merge = require('webpack-merge');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
const common = require('./webpack.common.js');

module.exports = merge(common, {
    devtool: 'source-map',
    plugins: [
        new UglifyJSPlugin({
            sourceMap: true,
            test: /\.js($|\?)/i,
            uglifyOptions: {
                compress: true
            }
        }),
        new webpack.LoaderOptionsPlugin({
            minimize: true,
            debug: false
        }),
        new webpack.DefinePlugin({
            'process.env.NODE_ENV': JSON.stringify('production')
        }),
    ]
});

tsconfig.json:

{
  "compilerOptions": {
    "outDir": "./dist/",
    "declaration": true,
    "declarationDir": "./types",
    "sourceMap": true,
    "noImplicitAny": true,
    "module": "commonjs",
    "target": "es6",
  }
}

package.json:

{
  "name": "bla",
  "version": "0.0.1",
  "description": "",
  "main": "index.ts",
  "types": "./dist/types/",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack --config webpack.prod.js",
    "start": "webpack-dev-server --open --config webpack.dev.js",
    "watch": "webpack --watch"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@types/gl-matrix": "^2.4.0",
    "@types/lodash": "^4.14.104",
    "@types/node": "^8.9.4",
    "@types/webgl2": "^0.0.2",
    "@types/webpack-dev-middleware": "^1.12.3",
    "clean-webpack-plugin": "^0.1.18",
    "file-loader": "^0.11.2",
    "html-webpack-plugin": "^2.30.1",
    "image-webpack-loader": "^3.6.0",
    "style-loader": "^0.18.2",
    "ts-loader": "^2.3.7",
    "ts-node": "^3.3.0",
    "tslint": "^5.9.1",
    "tslint-loader": "^3.5.3",
    "typescript": "^2.7.1",
    "uglifyjs-webpack-plugin": "^1.2.2",
    "webpack": "^3.11.0",
    "webpack-bundle-analyzer": "^2.11.0",
    "webpack-dev-middleware": "^1.12.0",
    "webpack-dev-server": "^2.11.2",
    "webpack-glsl-loader": "^1.0.1",
    "webpack-jarvis": "^0.3.0",
    "webpack-merge": "^4.1.2"
  },
  "dependencies": {
    "gl-matrix": "^2.4.0",
    "lodash-es": "^4.17.5"
  }
}

使用此配置,app.bundle.js 生成一个 507 KB 的文件,app.bundle.js.map 为 1.6 MB。如果我不 uglify 构建输出,我可以看到整个 lodash 库正在写入文件中。我还看到了一些其他函数,即 gl-matrix 被写入文件,尽管我什至没有使用它们。

我还在开发中运行webpack-bundle-analyzer,输出与生产没有区别。由于缩小,只有 budle 文件约为 1.4 MB 而不是 1.6 MB。

我在整个项目中只加载了两次lodash,比如:

import { some, find, cloneDeep } from 'lodash';

不再使用lodash 函数。为什么Webpack 会夸大我的app.bundle.js?

我的配置有问题吗?

【问题讨论】:

  • 尝试使用lodash-es,它应该可以工作!

标签: typescript webpack tree-shaking


【解决方案1】:

鉴于标准 lodash 包的现有导出样式,您有两种解决方案:

  1. 移至使用导出的 lodash 包,该包将直接插入到您的导入模式中。正如@alex-rokabilis 在评论中提到的,一个可用的包是lodash-es
  2. 更新您的导入以使用标准 lodash 包使用的导出。如果您查看lodash's npm page,您会发现它们支持从路径中挑选特定方法。

    import some from 'lodash/fp/some';
    import find from 'lodash/fp/find';
    import cloneDeep from 'lodash/fp/cloneDeep';
    

【讨论】:

    猜你喜欢
    • 2019-12-29
    • 2016-11-17
    • 2021-11-26
    • 2019-07-19
    • 2021-07-17
    • 2017-06-17
    • 2016-11-12
    • 2020-03-03
    • 2016-12-28
    相关资源
    最近更新 更多