webpack 全量打包 曾量打包_webpack js打包 不带webpack信息 - CSDN
精华内容
参与话题
  • webpack增量打包多页应用

    千次阅读 2019-01-09 14:14:03
    一,webpack打包存在的问题 webpack打包顺序: var path = require('path'); module.exports = { entry: { one: "./src/one.js", two: "./src/two.js" }, output: { path: path....

    一,webpack打包存在的问题

    webpack的打包顺序:

    var path = require('path');
    module.exports = {
        entry: {
            one: "./src/one.js",
            two: "./src/two.js"
        },
        output: {
            path: path.resolve(__dirname, 'dist'),
            filename: "[name].js"
        }
    };
    

    1,找到入口文件

    2,根据入口文件,找出具有依赖关系的文件js/css

    3,最后,把css/js全部打包成一个js包

    好的,打包完成,打包了整个世界,那么问题来了:


    产品说:按钮颜色不对,给我改成#ccc

    技术:好的,这就改。

    然后就有了如下流程:

    1,找到了entry -> js -> componet -> button.less修改了一个色值

    2,执行webpack打包

    这时就暴露了问题:

    1,明明只是修改了一个色值,却要从入口开始重新打包

    2,业务代码明明没有变化,却也被牵连了

    3,最后生成的js要全部推到线上,覆盖掉线上原本没问题的业务js,纯粹是增加风险

     

    二,思考解决方案

    首先想到的是,既然只修改一个文件,那能不能重新打包一个文件呢?

    1,单独打包更新的文件?

    这种方案,很快就被自我否定了。

    因为:

    1,从入口打包的文件,已经通过依赖关系,把老版本button.less打入了最终输出的js文件

    2,单独打包button.less输出了一个独立的button.js,这个文件需要手动引入到html中,一旦这类文件制造的多了,根本无法维护

    经过反复思考,单独打包每一个文件的想法,不符合webpack的设计初衷,从入口打包的流程是不能够产生变化的

    在这个问题上卡了真的很久.....很久

    2,能否通过依赖关系,打包某一个入口?

    由于我面临的场景是多页应用,所以存在多个入口,那么既然如此,那么能否通过依赖关系,找到需要更新的入口呢?

    这种方案,也思索了很久,后来也被否定了。

    因为:

    1,webpack没有适合输出模块依赖关系的插件,遍寻无果啊

    2,通过webpack的stats分析指标,能够输出依赖关系,但数据量太大,如果不加过滤,目前项目输出12W行json信息,还需要花力气处理一遍这个信息才能拿到关系

    3,如果一个组件被多个入口引用,那么需要找到每一个引用的入口点,再重新打包每个被波及的入口

    上面尤其是第三点,完全不符合我们想增量发布的目的,如果改了一个button组件,要重新打包二三十个入口,这完全没有增量发布的意义

    在这个问题上又纠结了很久......很久


    三,合理的解决方案

    经过前面两个问题后,我发现思考的方向完全是错误的,总是妄想改变webpack的打包方式,简直就是跟它的理念对着干。

    既然不能改变webpack的打包方式,那么我能否改变webpack的输出结果呢?

    其实webpack关于缓存方面的功能,提供了很多功能强大的插件,例如:

    • CommonsChunkPlugin可以用来在打包的时候提取公共js代码

    • ExtractTextPlugin可以用来从js中提出css,将其输出到一个独立的文件

    利用这两个插件,我们能够将我们打包的精度加以划分,将公共引用的部分打包为一个单独的文件

    如果公共引用的部分变为了一个单独的文件,再添加上hash进行缓存,当再次修改的时候只要更新hash,这样我们不就能够确定,究竟改动了哪个文件了吗

    既然如此,我们一步一步进行探索:

    1,首先使用CommonsChunkPlugin,提取公共js

    现在我们创建测试入口文件:

    src/one.js:

        import jquery from 'jquery';
        console.log('one');
    

    src/two.js:

        import jquery from 'jquery';
        console.log('two');
    

    webpack.config.js

    var path = require('path');
    module.exports = {
        entry: {
            one: "./src/one.js",
            two: "./src/two.js"
        },
        output: {
            path: path.resolve(__dirname, 'dist'),
            filename: "[name].js"
        }
    };
    

    执行webpack

     

     

    输出了2个文件,大小都是271kb,这是因为one.js和two.js都引用了jquery,jquery打包了2次,分别打包到了两个文件中

    这样显然不是很友好,像jquery这种文件,显然平时不会改动,还是缓存起来比较好,修改webpack.config.js

    var webpack = require("webpack");
    var path = require('path');
    module.exports = {
        entry: {
            one: "./src/one.js",
            two: "./src/two.js"
        },
        output: {
            path: path.resolve(__dirname, 'dist'),
            filename: "[name].js"
        },
        plugins:[
            new webpack.optimize.CommonsChunkPlugin({
                name: "common",
            }),
        ]
    };
    

    现在我们添加了CommonsChunkPlugin插件,它的作用是提取公共js,再次执行webpack

     

     

     

    可以看到one.js和two.js的大小已经不到1k了,而common则274k,可以看到jquery已经被打包到了common.js当中

    2,为文件添加hash

    var webpack = require("webpack");
    var path = require('path');
    module.exports = {
        entry: {
            one: "./src/one.js",
            two: "./src/two.js"
        },
        output: {
            path: path.resolve(__dirname, 'dist'),
            filename: "[name].[hash:6].js"
        },
        plugins:[
            new webpack.optimize.CommonsChunkPlugin({
                name: "common",
            }),
        ]
    };
    

    上面修改了output的输出内容[name].[hash].js

    现在执行webpack:

     

     

     

    可以看到打包的三个文件都有了hash,但需要主意,此时每个文件的hash都是一样的

    再次执行一遍webpack:

     

     

    可以看到,两次构建输出的结果一致,这很好,因为没有修改文件,自然不希望hash发生改变

    那么接下来,修改一下文件:one.js

    import jquery from 'jquery';
    console.log('修改one');
    

     

     

    悲剧了,所有文件全部修改了hash,查看输出的结果:

     

     

    可以发现只修改一个文件,却修改了全部文件的hash,这个问题很严重,显然不是我们想要的

    3,使用chunkhash替代hash

    webpack中关于缓存,提供了好几种添加hash的方法,其中就有chunkhash

    chunkhash简单来说,就是根据模块内容来添加hash,既然这样的话,只要文件没有改变,就不会生成新的hash

    var webpack = require("webpack");
    var path = require('path');
    module.exports = {
        entry: {
            one: "./src/one.js",
            two: "./src/two.js"
        },
        output: {
            path: path.resolve(__dirname, 'dist'),
            filename: "[name].[chunkhash:8].js"
        },
        plugins:[
            new webpack.optimize.CommonsChunkPlugin({
                name: "common",
            }),
        ]
    };
    

    如上图,修改filename:[name].[chunkhash:8]/js

    执行webpack

     

     

    可以看到这一次生成的hash是4897....

    但是输出的每个文件的hash却不是4897....

    很好,接下来再执行一次webpack:

     

     

    可以看到两次输出之间hash并没有发生变化

    现在,修改one.js,再执行webapck

    import jquery from 'jquery';
    console.log('使用chunkhash后修改one');
    

     

     

    可以看到two.js的hash没有改变one.js的hash改变了,但common.js的hash竟然也改了...

    4,提取manifest

    前面用CommonsChunkPlugin提取代码后,公共的代码已经被抽离,但是他们之间肯定存在一个映射关系,例如

     

     

    之所以commonjs的hash会变,是因为修改one.js生成了新的hash,而jquery又与one.js存在映射关系,映射关系会更新,也就是说common.js它要从新的one.js中提取了jquery

    manifest就可以简单理解为模块映射关系的集合,而这个manifest将随着这些被分离出来的代码共同打包!!!

    所以现在分离manifest

    var webpack = require("webpack");
    var path = require('path');
    module.exports = {
        entry: {
            one: "./src/one.js",
            two: "./src/two.js"
        },
        output: {
            path: path.resolve(__dirname, 'dist'),
            filename: "[name].[chunkhash:8].js"
        },
        plugins:[
            new webpack.optimize.CommonsChunkPlugin({
                name: "common",
            }),
            new webpack.optimize.CommonsChunkPlugin({
                name: 'manifest' // 用于提取manifest
            })
        ]
    };
    

    这里主要是利用CommonsChunkPlugin的一个功能,通过默认的名字,来提取公共代码,因为webpack打包的是有有一个默认模块就是manifest,所以我们可以通过这个来实现

    现在我们执行webpack:

     

     

    可以看到,多输出了一个manifest.js

    接下来,再修改one.js

    import jquery from 'jquery';
    console.log('分离manifest后修改one');
    

     

     

    可以看到,现在只有one.js和manifest.js的hash发生了改变,common.js被成功缓存了

    使用代码对比工具,比较两次manifest之间的区别,可以看到确实是映射的chunkid发生了改变

     

     

    5,使用webpack-md5-hash插件

    前面我们输出了一个manifest.js,但这样还需要单独处理这个manifest.js,所以可以使用webpack的另一个插件webpack-md5-hash

    var webpack = require("webpack");
    var WebpackMd5Hash = require('webpack-md5-hash');
    var path = require('path');
    module.exports = {
        entry: {
            one: "./src/one.js",
            two: "./src/two.js"
        },
        output: {
            path: path.resolve(__dirname, 'dist'),
            filename: "[name].[chunkhash:8].js"
        },
        plugins:[
            new WebpackMd5Hash(),
            new webpack.optimize.CommonsChunkPlugin({
                name: "common",
            }),
        ]
    };
    
    

    执行一次打包:

     

     

    没有manifest输出,修改one.js

    import jquery from 'jquery';
    console.log('使用WebpackMd5Hash修改one');
    

    再次打包:

     

     

    这一次仅有one.js的hash发生了改变

    虽然webpack-md5-hash解决了我们的问题,但这也让打包的模块关系变成了黑盒,存在一定的未知风险,还需要仔细实践评估是否有问题

    6,打包修改频率超级低的库

    前面已经抽离出来了公共代码,但是还存在问题,假如这时候又需要引入lodash,那common的hash是否会改变?

    修改one.js

    import jquery from 'jquery';
    import lodash from 'lodash';
    console.log('引入lodash修改one');
    

    修改two.js

    import jquery from 'jquery';
    import lodash from 'lodash';
    console.log('引入lodash修改two');
    

     

     

    这一次,所有文件的hash都发生了改变,不仅如此,而且更显著的是common的体积增大了

    这就意味者lodash也被打进了common当中,但这本身是一个错误的行为,lodash和jquery,平时根本不会对其进行修改,既然如此,那还需要优化,把他们单独打包出去

    现在修改webapack.config.js

    var webpack = require("webpack");
    var WebpackMd5Hash = require('webpack-md5-hash');
    var path = require('path');
    module.exports = {
        entry: {
            two: "./src/two.js",
            one: "./src/one.js",
            common:['jquery','lodash']
        },
        output: {
            path: path.resolve(__dirname, 'dist'),
            filename: "[name].[chunkhash:8].js"
        },
        plugins:[
            new WebpackMd5Hash(),
            new webpack.optimize.CommonsChunkPlugin({
                name: "common",
            }),
        ]
    };
    

    这一次在入口处添加了一个common,common单独指向了jquery和lodash,这一次我们执行打包

     

     

    此时,输出的内容没有明显变化,同样是3个文件,大小也完全一致,hash也没有问题

    可以看到,common的大小是817k

    如果这时,再应用了其他的包呢?例如引入react

    修改one.js

    import jquery from 'jquery';
    import lodash from 'lodash';
    import react from 'react';
    console.log('引入react修改one');
    

    修改two.js

    import jquery from 'jquery';
    import lodash from 'lodash';
    import react from 'react';
    console.log('引入react修改one');
    

    执行webpack

     

     

    问题来了,common的大小增加了,很显然react被打包进去了,但如果我们此时,只想永久缓存jquery和lodash呢,这该怎么办?

    修改webpack.config.js

    var webpack = require("webpack");
    var WebpackMd5Hash = require('webpack-md5-hash');
    var path = require('path');
    module.exports = {
        entry: {
            two: "./src/two.js",
            one: "./src/one.js",
            common:['jquery','lodash']
        },
        output: {
            path: path.resolve(__dirname, 'dist'),
            filename: "[name].[chunkhash:8].js"
        },
        plugins:[
            new WebpackMd5Hash(),
            new webpack.optimize.CommonsChunkPlugin({
                name: 'common',
                minChunks:Infinity
            })
        ]
    };
    

    这一次,添加了一句话minChunks:Infinity

    minChunks属性的可以设置为2,意思是引用次数为2的模块就抽离出来,而Infinity则表示无限,无限就意味着不会有多余的被打包进来

    现在执行webpack打包

     

     

    可以看到现在common又恢复了816k,当然react也没有抽出来,还在两个文件当中,接下来继续抽离react

    var webpack = require("webpack");
    var WebpackMd5Hash = require('webpack-md5-hash');
    var path = require('path');
    module.exports = {
        entry: {
            two: "./src/two.js",
            one: "./src/one.js",
            common:['jquery','lodash'],
            react:['react','react-redux']
        },
        output: {
            path: path.resolve(__dirname, 'dist'),
            filename: "[name].[chunkhash:8].js"
        },
        plugins:[
            new webpack.optimize.CommonsChunkPlugin({
                name: ['react','common'], // 用于提取manifest
                minChunks:Infinity
            }),
            new WebpackMd5Hash(),
        ]
    };
    

     

     

    通过上面的构建,我们已经将不会改动的类库,单独打包并维持住了hash。

    7,引入HashedModuleIdsPlugin固定模块id

    前面看似完美,但如果我们现在改变一下入口的顺序

    entry: {
        react:['react','react-redux'],        
        two: "./src/two.js",
        one: "./src/one.js",
        common:['jquery','lodash'],        
    }
    

     

     

    可以看到common和react公共库的hash又变了,这是因为,模块id是根据webpack的解析顺序增量的,如果变换解析顺序,那模块id也会随之改变。

    所以就需要HashedModuleIdsPlugin了,它是根据模块相对路径生成模块标识,如果模块没有改变,那模块标识也不会改变

    var webpack = require("webpack");
    var WebpackMd5Hash = require('webpack-md5-hash');
    var path = require('path');
    module.exports = {
        entry: {
            common:['jquery','lodash'],                
            react:['react','react-redux'],        
            two: "./src/two.js",
            one: "./src/one.js",
        },
        output: {
            path: path.resolve(__dirname, 'dist'),
            filename: "[name].[chunkhash:8].js"
        },
        plugins:[
            new webpack.optimize.CommonsChunkPlugin({
                name: ['react','common'], // 用于提取manifest
                minChunks:Infinity
            }),
            new webpack.HashedModuleIdsPlugin(),
            new WebpackMd5Hash(),
        ]
    };
    

     

     

    现在打包后,模块的标识不再是id了,而是一个四位的编码了,这样就可以固定住ip地址了。

    8,使用extract-text-webpack-plugin提取css文件

    在src下创建one.css:

    body{
        color:blue;
    }
    

    two.css

    h1{
        font-size:24px;
    }
    

    修改one.js和two.js引入css

    import jquery from 'jquery';
    import lodash from 'lodash';
    import react from 'react';
    import './one.css'
    console.log('引入css修改one');
    

    修改webpack.config.js

    var webpack = require("webpack");
    var WebpackMd5Hash = require('webpack-md5-hash');
    var path = require('path');
    var ExtractTextPlugin = require("extract-text-webpack-plugin");
    module.exports = {
        entry: {
            common: ['jquery', 'lodash'],
            react: ['react', 'react-redux'],
            two: "./src/two.js",
            one: "./src/one.js",
        },
        output: {
            path: path.resolve(__dirname, 'dist'),
            filename: "[name].[chunkhash:8].js"
        },
        module: {
            rules: [
                {
                    test: /\.css$/,
                    use: ExtractTextPlugin.extract({
                        fallback: "style-loader",
                        use: "css-loader"
                    })
                }
            ]
        },
        plugins: [
            new webpack.optimize.CommonsChunkPlugin({
                name: ['react', 'common'], // 用于提取manifest
                minChunks: Infinity
            }),
            new ExtractTextPlugin("[name].[chunkhash:8].css"),
            new webpack.HashedModuleIdsPlugin(),
            new WebpackMd5Hash()
        ]
    };
    

    执行webpack:

     

     

    可以看到,成功输出了js和css,但是有点疑问的是,one.css和one.js的hash是一样的,这样的话,如果我们改变one.css呢?

    修改one.css,再次打包:

     

     

    发现css的hash没有任何变化。

    接着再修改one.js,再次打包:

     

     

    这一次one.js和one.css的hash同时改变了。

    9,使用contenthash提取固定css的hash

    • When using the ExtractTextWebpackPlugin, use [contenthash] to obtain a hash of the extracted file (neither [hash] nor [chunkhash] work).

    webpack output文档种有写,当提取css后,用contenthash添加hash

    var webpack = require("webpack");
    var WebpackMd5Hash = require('webpack-md5-hash');
    var path = require('path');
    var ExtractTextPlugin = require("extract-text-webpack-plugin");
    module.exports = {
        entry: {
            common: ['jquery', 'lodash'],
            react: ['react', 'react-redux'],
            two: "./src/two.js",
            one: "./src/one.js",
        },
        output: {
            path: path.resolve(__dirname, 'dist'),
            filename: "[name].[chunkhash:8].js"
        },
        module: {
            rules: [
                {
                    test: /\.css$/,
                    use: ExtractTextPlugin.extract({
                        fallback: "style-loader",
                        use: "css-loader"
                    })
                }
            ]
        },
        plugins: [
            new webpack.optimize.CommonsChunkPlugin({
                name: ['react', 'common'], // 用于提取manifest
                minChunks: Infinity
            }),
            new ExtractTextPlugin("[name].[contenthash:8].css"),
            new webpack.HashedModuleIdsPlugin(),
            new WebpackMd5Hash()
        ]
    };
    

    这一次,只是修改了输出的hash,conenthash代表的是文本文件内容的hash值,也就是只有style文件的hash值。

    执行webpack:

     

     

    one.js和one.css的hash变的不一样了

    接下来,修改one.css

    body{
        color:white;
    }
    

    再次执行webpack:

     

     

    至此,只有one.css发生了变化,准备工作基本就到这里了

    四,优化多页打包时间,稳定hash

    1,约束入口

    因为是多页应用,是通过扫入口文件来进行的打包,规则为js文件为入口文件,jsx为引用的资源不被识别为入口

    通过BundleAnalyzerPlugin插件分析,发现有部分组件被打包为了入口,梳理一遍后,重新打包,打包时间减少了2/3,当然这是在填以前的坑

     

     

    生产打包时间是74578ms

    此时压缩和不压缩的打包时间也是3倍的关系:

     

     

    开发打包时间是24780ms

    好的,围绕这两个时间,我们开始优化

    2,使用UglifyjsWebpackPlugin开启多线程打包

    首先要做的其实是稳定hash,但因为生产环境的打包速度太慢,所以我们先优化打包速度,webpack默认提供的打包是单线程的

    const UglifyJSPlugin = require('uglifyjs-webpack-plugin')
    
    module.exports = {
      plugins: [
        new UglifyJSPlugin({
            parallel: true
        })
      ]
    }
    

    这个插件是webpack3提供的,至于低版本webapck的话,需要谨慎处理,不过效果很明显

     

     

    现在生产打包时间是51690ms,比之前提速了1/3

    3,使用HappyPack多线程加速loader

    var HappyPack = require('happypack');
    var os = require('os');
    var happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length });
    
    ...
    module: {
            rules: [ {
                test: /\.js[x]?$/,
                exclude: /(node_modules|bower_components)/,
                loader: 'happypack/loader?id=happybabel',
                include: path.join(__dirname, 'static/assets/js')
            }
        }
    plugins: [
            new HappyPack({
                id: 'happybabel',
                loaders: ['babel-loader?cacheDirectory=true'],
                threadPool: happyThreadPool,
                cache: true,
                verbose: true
              }),
    

    上面module的rules属性中loader原本事babel-loader,现在将它变成了一个任务,其中有一个id,id对应的就是plugins中的happyPack实例

     

     

    此时,我们开启了babel-loader的多线程模式

    现在生产打包时间是43855ms,比之前又提速了1/9,这只是babel-loader,我们还可以为其它的loader开启

    接着处理less,css,style等loader,这些结合可以一口气搞定

        module: {
            rules: [{
                test: require.resolve('zepto'),
                loader: 'exports-loader?window.Zepto!script-loader'
            }, {
                test: /\.js[x]?$/,
                exclude: /(node_modules|bower_components)/,
                loader: 'happypack/loader?id=happybabel',
                include: path.join(__dirname, 'static/assets/js')
            }, {
                test: /\.less$/,
                use: extractTextPlugin.extract({
                    fallback: "style-loader",
                    // use: ["css-loader" + (ENV ? '?minimize' : ''), "less-loader", "postcss-loader"]
                    use: ["happypack/loader?id=postcss"]
                })
            }]
        }
    plugins: [
            new HappyPack({
                id: 'happybabel',
                loaders: ['babel-loader?cacheDirectory=true'],
                threadPool: happyThreadPool,
                // cache: true,
                verbose: true
            }),
            new HappyPack({
                id: 'postcss',
                loaders: ["css-loader" + (ENV ? '?minimize' : ''), "less-loader",'postcss-loader'],
                threadPool: happyThreadPool,
                // cache: true,
                verbose: true
            }),
    

    这样,我们即处理了babel,同时也搞定了css,less,postcss这些loader

     

     

    上图happy[任务名],可以看到打包行为全都开启了多线程,效果显著

    现在生产打包时间是35130ms,此时已经比第一此非优化的时候,提升了一倍的速度

    4,使用dll拆分代码

    经过前面的过程,想必已经意识到了纯静态得库和组件都需要与打包环节分离开,这就需要dll技术了

    dll技术,其实就是将修改频率低或基本不修改且引用次数多的内容,单独打包

    因为设计dll后,config文件的数量剧增,所以需要重新整理目录结构

     

     

    例如上图,将每一个webpack拆分出去,把所有配置文件分离开,例webpack.dev.js:

    var base = require('./webpack.base.js');
    var config = {
        entry: require('./dev/entry.js'),
        output: require('./dev/output.js'),
        plugins: require('./dev/plugins.js'),
        devtool: 'eval-source-map'
    }
    //把配置文件暴露出去;
    module.exports = Object.assign(base,config);
    
    

    ok,基础拆分webpack完成后,我们创建一个webpack.dll.libs.js用于打包类库

    module.exports = {
        libs: [
            'react',
            'react-dom',
            'react-motion',
            'react-redux',
            'redux',
            'axios',
            'prop-types',
            'classnames',
        ]
    }
    

    修改plugins插件:

    var webpack = require('webpack');
    var dirVars = require('../common/dir.js');
    var path = require('path');
    var UglifyJsPlugin = require('uglifyjs-webpack-plugin');//多线程打包
    var getDefaultPlugins = require('../common/plugins.js').getDefaultPlugins;
    var AssetsPlugin = require('assets-webpack-plugin');//输出映射表
    
    var plugins =[
        new webpack.DllPlugin({
            path: dirVars.dllLibsManiFest,
        }),
        new UglifyJsPlugin({
            parallel: true,
            cache: true
        }),
        new AssetsPlugin({
            filename: 'static/dll/libs-rev-manifest.json'
        }),
    ]
    module.exports = plugins.concat(getDefaultPlugins())
    

    现在执行webpack

     

     

    可以看到,只需要1s,就打包了所有的类库,接下来,修改webpack.prod.js

    在plugins中添加:

    new webpack.DllReferencePlugin({
        manifest: 'static/dll/libs-rev-manifest.json'
    }),
    

    此时当我们执行webpack.prod.js进行打包,当扫描到libs中的打包的内容时,就不会重复打包

    4,开始继续约束hash

    前面已经彻底搞定了打包,但破坏性很大,所以需要系统的验证hash是否存在问题

    case1:js改变

    修改一个业务代码的js,添加一句注释,再次打包

     

     

    可以看到文件hash发生了改变,但很不幸,vendor也发生了改变

     

     

    解决方案:添加webpack-md5-hash插件,使用之后,再次验证,发现vendorjs的hash不再发生变化

    case2:less改变

     

     

    只有一个css的hash发生了变化,没问题

    case3:修改一个入口下自己封装出去的公共方法

     

     

    上面修改了一个入口内公共使用的tools插件,最终是入口的hash发生了改变,没问题

    case4:修改公共方法组件js

    主要是多个入口都会引用的组件

     

     

    测试,只有单独打包出去的components的hash修改了

    case5:修改公共方法组件less

     

     

    只有一个hash发生了改变

    case6:添加一个公共组件

     

     

    只有components的hash发生了改变

    未优化前打包时间180-200s

    优化:

    1,约束入口,严格明确入口文件筛选条件后
        生产打包:74578ms
        开发打包:24780ms
    2,开启多线程压缩后
        生产打包:51690ms
    3,开启多线程编译
        生产打包:35130ms
        开发打包:15031ms
    4,拆包
        分解了打包过程,类库4s,组件4s,业务20s,总体30s左右
    

    最终,流程变得可控,打包实现了定制化,hash得到了保持。

    如何学习大数据?学习没有资料?

    想学习大数据开发技术,Hadoop,spark,云计算,数据分析等技术,在这里向大家推荐一个学习资料分享群:894951460,里面有大牛已经整理好的相关学习资料,希望对你们有所帮助。

    展开全文
  • webpack打包分析与性能优化

    千次阅读 2018-01-02 09:46:57
    在去年年末参与的一个项目中,项目技术栈使用react+es6+ant-design+webpack+babel,生产环境全量构建将近三分钟,项目业务模块多达数百个,项目依赖数千个,并且该项目协同前后端开发人员较多,提高webpack 构建效率...

    背景

    在去年年末参与的一个项目中,项目技术栈使用react+es6+ant-design+webpack+babel,生产环境全量构建将近三分钟,项目业务模块多达数百个,项目依赖数千个,并且该项目协同前后端开发人员较多,提高webpack 构建效率,成为了改善团队开发效率的关键之一。

    下面我将在项目中遇到的问题和技术方案沉淀出来与大家做个分享

    从项目自身出发

    我们的项目是将js分离,不同页面加载不同的js。然而分析webpack打包过程并针对性提出优化方案是一个比较繁琐的过程,首先我们需要知道webpack 打包的流程,从而找出时间消耗比较长的步骤,进而逐步进行优化。

    在优化前,我们需要找出性能瓶颈在哪,代码组织是否合理,优化相关配置,从而提升webpack构建速度。

    1.使用yarn而不是npm

    由于项目使用npm安装包,容易导致在多关联依赖关系中,很可能某个库在指定依赖时没有指定版本号,进而导致不同设备上拉到的package版本不一。yarn不管安装顺序如何,相同的依赖关系将以相同的方式安装在任何机器上。当关联依赖中包括对某个软件包的重复引用,在实际安装时将尽量避免重复的创建。yarn不仅可以缓存它安装过的包,而且安装速度快,使用yarn无疑可以很大程度改善工作流和工作效率

    2.删除没有使用的依赖

    很多时候,我们由于项目人员变动比较大,参与项目的人也比较多,在分析项目时,我发现了一些问题,诸如:有些文件引入进来的库没有被使用到也没有及时删除,例如:

    import a from 'abc';
    

    在业务中并没有使用到a 模块,但webpack 会针对该import 进行打包一遍,这无疑造成了性能的浪费。

    webpack打包分析

    1.打包过程分析

    我们知道,webpack 在打包过程中会针对不同的资源类型使用不同的loader处理,然后将所有静态资源整合到一个bundle里,以实现所有静态资源的加载。webpack最初的主要目的是在浏览器端复用符合CommonJS规范的代码模块,而CommonJS模块每次修改都需要重新构建(rebuild)后才能在浏览器端使用。

    那么, webpack是如何进行资源的打包的呢?总结如下:

    • 对于单入口文件,每个入口文件把自己所依赖的资源全部打包到一起,即使一个资源循环加载的话,也只会打包一份
    • 对于多入口文件的情况,分别独立执行单个入口的情况,每个入口文件各不相干

    我们的项目使用的就是多入口文件。在入口文件中,webpack会对每个资源文件进行配置一个id,即使多次加载,它的id也是一样的,因此只会打包一次。

    实例如下:
    main.js引用了chunk1、chunk2,chunk1又引用了chunk2,打包后:bundle.js:

     ...省略webpack生成代码
    /************************************************************************/
    /******/ ([
    /* 0 */
    /***/ function(module, exports, __webpack_require__) {
    
        __webpack_require__(1);//webpack分配的id
        __webpack_require__(2);
    
    /***/ },
    /* 1 */
    /***/ function(module, exports, __webpack_require__) {
    	//chunk1.js文件
        __webpack_require__(2);
        var chunk1=1;
        exports.chunk1=chunk1;
    
    /***/ },
    /* 2 */
    /***/ function(module, exports) {
    	//chunk2.js文件
        var chunk2=1;
        exports.chunk2=chunk2;
    
    /***/ }
    /******/ ]);
    

    2.如何定位webpack打包速度慢的原因

    我们首先需要定位webpack打包速度慢的原因,才能因地制宜采取合适的方案。我么可以在终端中输入:

    $ webpack --profile --json > stats.json
    

    然后将输出的json文件到如下两个网站进行分析

    这两个网站可以将构建后的组成用可视化的方式呈现出来,可以让你清楚的看到模块的组成部分,以及在项目中可能存在的多版本引用的问题,对于分析项目依赖有很大的帮助

    优化方案与思路

    针对webpack构建大规模应用的优化往往比较复杂,我们需要抽丝剥茧,从性能提升点着手,可能没有一套通用的方案,但大体上的思路是通用的,核心思路可能包括但不限于如下:

    1):拆包,限制构建范围,减少资源搜索时间,无关资源不要参与构建

    2):使用增量构建而不是全量构建

    3):从webpack存在的不足出发,优化不足,提升效率

    webpack打包优化

    1.减小打包文件体积

    webpack+react的项目打包出来的文件经常动则几百kb甚至上兆,究其原因有:

    • import css文件的时候,会直接作为模块一并打包到js文件中
    • 所有js模块 + 依赖都会打包到一个文件
    • React、ReactDOM文件过大

    针对第一种情况,我们可以使用 extract-text-webpack-plugin,但缺点是会产生更长时间的编译,也没有HMR,还会增加额外的HTTP请求。对于css文件不是很大的情况最好还是不要使用该插件。

    针对第二种情况,我们可以通过提取公共代码块,这也是比较普遍的做法:

     new webpack.optimize.CommonsChunkPlugin('common.js');
    

    通过这种方法,我们可以有效减少不同入口文件之间重叠的代码,对于非单页应用来说非常重要。

    针对第三种情况,我们可以把React、ReactDOM缓存起来:

        entry: {
            vendor: ['react', 'react-dom']
        },
        new webpack.optimize.CommonsChunkPlugin('vendor','common.js'),
    

    我们在开发环境使用react的开发版本,这里包含很多注释,警告等等,部署线上的时候可以通过 webpack.DefinePlugin来切换生产版本。

    当然,我们还可以将React 直接放到CDN上,以此来减少体积。

    2.代码压缩

    webpack提供的UglifyJS插件由于采用单线程压缩,速度很慢 ,
    webpack-parallel-uglify-plugin插件可以并行运行UglifyJS插件,这可以有效减少构建时间,当然,该插件应用于生产环境而非开发环境,配置如下:

    var ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin');
    new ParallelUglifyPlugin({
       cacheDir: '.cache/',
       uglifyJS:{
         output: {
           comments: false
         },
         compress: {
           warnings: false
         }
       }
     })
    

    3.happypack

    happypack 的原理是让loader可以多进程去处理文件,原理如图示:


    此外,happypack同时还利用缓存来使得rebuild 更快

    var HappyPack = require('happypack'),
      os = require('os'),
      happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length });
    
    modules: {
    	loaders: [
    	  {
            test: /\.js|jsx$/,
            loader: 'HappyPack/loader?id=jsHappy',
            exclude: /node_modules/
          }
    	]
    }
    
    plugins: [
        new HappyPack({
          id: 'jsHappy',
          cache: true,
          threadPool: happyThreadPool,
          loaders: [{
            path: 'babel',
            query: {
              cacheDirectory: '.webpack_cache',
              presets: [
                'es2015',
                'react'
              ]
            }
          }]
        }),
        //如果有单独提取css文件的话
        new HappyPack({
          id: 'lessHappy',
          loaders: ['style','css','less']
        })
      ]
    

    4.缓存与增量构建

    由于项目中主要使用的是react.js和es6,结合webpack的babel-loader加载器进行编译,每次重新构建都需要重新编译一次,我们可以针对这个进行增量构建,而不需要每次都全量构建。

    babel-loader可以缓存处理过的模块,对于没有修改过的文件不会再重新编译,cacheDirectory有着2倍以上的速度提升,这对于rebuild 有着非常大的性能提升。

    var node_modules = path.resolve(__dirname, 'node_modules');
    var pathToReact = path.resolve(node_modules, 'react/react');
    var pathToReactDOM = path.resolve(node_modules,'react-dom/index');
    
    {
            test: /\.js|jsx$/,
            include: path.join(__dirname, 'src'),
            exclude: /node_modules/,
            loaders: ['react-hot','babel-loader?cacheDirectory'],
            noParse: [pathToReact,pathToReactDOM]
    }
    

    babel-loader让除了node_modules目录下的js文件都支持es6语法,注意exclude: /node_modules/很重要,否则 babel 可能会把node_modules中所有模块都用 babel 编译一遍!
    当然,你还需要一个像这样的.babelrc文件,配置如下:

    {
      "presets": ["es2015", "stage-0", "react"],
      "plugins": ["transform-runtime"]
    }
    

    这是一劳永逸的做法,何乐而不为呢?除此之外,我们还可以使用webpack自带的cache,以缓存生成的模块和chunks以提高多个增量构建的性能。

    在webpack的整个构建过程中,有多个地方提供了缓存的机会,如果我们打开了这些缓存,会大大加速我们的构建

    而针对增量构建 ,我们一般使用:

    webpack-dev-server或webpack-dev-middleware,这里我们使用webpack-dev-middleware:

    webpackDevMiddleware(compiler, {
                        publicPath: webpackConfig.output.publicPath,
                        stats: {
                          chunks: false,
                          colors: true
                        },
                        debug: true,
                        hot: true,
                        lazy: false,
                        historyApiFallback: true,
                        poll: true
                    })
    

    通过设置chunks:false,可以将控制台输出的代码块信息关闭

    5.减少构建搜索或编译路径

    为了加快webpack打包时对资源的搜索速度,有很多的做法:

    • Resolove.root VS Resolove.moduledirectories

    大多数路径应该使用resolve.root,只对嵌套的路径使用 Resolove.moduledirectories,这可以获得显著的性能提升

    原因是Resolove.moduledirectories是取相对路径,所以比起resolve.root会多parse很多路径:

    resolve: {
        root: path.resolve(__dirname,'src'),
        modulesDirectories: ['node_modules']
      },
    
    • DLL & DllReference

    针对第三方NPM包,这些包我们并不会修改它,但仍然每次都要在build的过程消耗构建性能,我们可以通过DllPlugin来前置这些包的构建,具体实例:webpack/webpack

    • alias和noPase

    resolve.alias是webpack 的一个配置项,它的作用是把用户的一个请求重定向到另一个路径。 比如:

    resolve: {  // 显示指出依赖查找路径
        alias: {
            comps: 'src/pages/components'
        }
    }
    

    这样我们在要打包的脚本中的使用 require('comps/Loading.jsx');其实就等价于require('src/pages/components/Loading.jsx')。

    webpack 默认会去寻找所有 resolve.root 下的模块,但是有些目录我们是可以明确告知 webpack 不要管这里,从而减轻 webpack 的工作量。这时会用到module.noParse 参数

    在项目中合理使用 alias 和 noParse 可以有效提升效率,虽然不是很明显

    以上配置均由本人给出,仅供参考(有些插件的官方文档给的不是那么明晰)

    6.其他

    • 开启devtool: "#inline-source-map"会增加编译时间
    • css-loader 0.15.0+ 使webpack加载变得缓慢
    //css-loader 0.16.0
    Hash: 8d3652a9b4988c8ad221
    Version: webpack 1.11.0
    Time: 51612ms
    
    //以下是css-loader 0.14.5
    Hash: bd471e6f4aa10b195feb
    Version: webpack 1.11.0
    Time: 6121ms
    
    • 对于ant-design模块,使用babel-plugin-import插件来按需加载模块
    • DedupePlugin插件可以在打包的时候删除重复或者相似的文件,实际测试中应该是文件级别的重复的文件

    结尾


    虽然上面的做法减少了文件体积,加快了编译速度,整体构建(initial build)从最初的三分多钟到一分钟,rebuild十多秒,优化效果明显。但对于Webpack + React项目来说,性能优化方面远不止于此,还有很多的优化空间,比如服务端渲染,首屏优化,异步加载模块,按需加载,代码分割等等

    文章转载自:github.com/hawx1993/tec
    展开全文
  • 之前修改公司的运营系统,多年来积累下来的代码使得每次打包构建的时候时间异常漫长,非常难受,一气之下将项目的Webpack从2.x升级到了4.x,原来在Jenkins上一套需要6分钟的流程现在只需2分钟,顿时感到身心舒畅( ̄...

    之前修改公司的运营系统,多年来积累下来的代码使得每次打包构建的时候时间异常漫长,非常难受,一气之下将项目的Webpack从2.x升级到了4.x,原来在Jenkins上一套需要6分钟的流程现在只需2分钟,顿时感到身心舒畅( ̄▽ ̄)/
    并且我顺便把项目划分成多入口项目,实现增量更新,这样就不用每次都打包这么多文件啦!

    ps:以下配置基于React,可以自行根据实际项目用到的框架和库修改


    1. 配置中可优化的点

    先说一下我在升级中发现的可以优化的点,大家有什么建议和想法可以一并提出。

    1.1 优化第三方库

    优化第三方库最简单粗暴并且及其有效的一个方式就是使用webpack的DllPlugin。它可以将我们经常使用但是修改频率极低的第三方库与自己的代码完全分离开, 每次打包的时候会根据索引判断是否需要重新打包第三方库,大大提高了打包速度。用法我就不细说了,网上有很多教程,感兴趣的可以去了解下。
    库的索引一般保存在一个manifest.json文件中。我们可以通过这个文件看到自己项目对第三方库的打包情况。

    优化思路:

    • 项目里安装的第三方库的需要评估必要性,如果很少使用到库的不要在webpackvendor入口指定打包进来。
    • 同时可以升级某些第三方库,如react v16对比react v15,加上react-dom,体积上降低了30%,因此果断升级。
    • 分析manifest.json文件后发现某些库体积特别大,例如使用很广泛的moment.js库。研究后发现webpack把库下面所有的locale文件打包了进来。这是一些支持多语言的文件。即我们可以通过ContextReplacementPlugin插件来挑选我们需要的文件。
    plugins: [
        new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /zh-cn/),
    ]
    复制代码
    • 有时候通过依赖分析会发现项目里打包了两份第三方库,一份是es module版的,另一份则是umd版的。如moment通过import 'moment'导入的是es module版的,locale文件中却会用相对路径导入umd版的。这时我们可以通过配置别名将库指向同一个版本。
    resolve: {
        alias: {
            'moment$': path.resolve('node_modules/moment/moment'),
        },
    }
    复制代码
    • 有时候项目里并不需要某个库的全部功能,这时候可以考虑用更轻量的库来替代,或者使用定制阉割版(如Echarts, 官网上可定制),并且用import()语法和react-loadable这个库将react组件包装成异步组件,在需要时才进行加载,这样webpack就会将异步组件抽取为异步加载的chunk,就不会多次加载。下面就说如何抽取。

    1.2 抽取异步加载的chunk中的公共代码

    在webpack4之前,我们使用CommonsChunkPlugin来抽取异步组件,但现在CommonsChunkPlugin已经被废弃了,取而代之的是SplitChunksPlugin
    使用方法有两种,一种是像Webpack3那样在plugins中配置,一种是在Webpack4中的optimization属性中的splitChunks配置

        optimization: {
          splitChunks: { // 拆分代码规则(符合即单独拆分到一个chunk中)
            maxInitialRequests: 4, // 在初始化加载时,请求数量大于4
            automaticNameDelimiter: '-',
            name: true, // 代码块的名字,设置为true则表示根据模块和缓存组秘钥自动生成, 实现固化 chunkId,保持缓存的能力
            
            /* 缓存组,用于继续细分代码。
            缓存组默认将node_modules中的模块拆分带一个叫做vendors的代码块, 将最少重复引用两次的模块放入default中。
            或者自定义将符合规则的模块单独拆分进一个chunk中。*/
            
            cacheGroups: {
              default: false, // 禁用默认规则
              vendors: false, // 禁用默认规则
              polyfill: {
                chunks: 'initial',
                test: 'polyfill',
                name: 'polyfill',
              },
              vendor: {
                chunks: 'initial',
                test: 'vendor',
                name: 'vendor',
              },
              // 对异步组件进行抽取
              'async-vendor': {
                name: 'async-vendor',
                chunks: 'async',
                test: (module) => { // 缓存组的规则,表示符合条件的的放入当前缓存组
                  if (/[\\/]node_modules[\\/](echarts|zrender)/.test(module.context)) {
                    return false;
                  }
                  return /[\\/]node_modules[\\/]/.test(module.context);
                },
              },
              'async-biz': {
                name: 'async-biz',
                chunks: 'async',
                minChunks: 2, // 被引用次数大于2时进行拆分
              },
              // css文件单独打包进一个文件中
              'styles': {
                name: 'styles',
                test: /\.css$/,
                chunks: 'async',
                enforce: true,
              },
            },
          },
        },
    复制代码

    当抽取异步加载组件时,我们需要在业务代码中使用下面的写法,webpack才能识别:
    基于react-loadable库,简介: React Loadable 简介

    import Loadable from 'react-loadable';
    const loder1 = import(/* webpackChunkName: "chunkname2" */'path/to/module2')
    const Component = Loadable({
        loader,
        loadingComponent, // loding时使用的组件
    })
    复制代码

    1.3 合理使用异步加载

    若我们项目中的首屏也是使用异步加载的方法,并且用到了async-vendor里的组件,首屏加载时就会同时加载async-vendor并做缓存,这样之后的页面使用到了async-vendor里面的组件之后就无需再次加载新的代码。但是这样就会可能拖慢我们的的首屏速度。
    解决办法一是拆分async-vendor的首屏部分;或是取消首屏页面的异步加载,将其打包到main中,这样就避免了加载async-vendor,大大减少了首屏体积。

    1.4 分离出webpack runtime代码

    webpack在客户端运行时会首先加载webpack相关的代码,例如require函数等,这部分代码会随着每次修改业务代码后发生变化,原因是这里面会包含chunk id等容易变化的信息。如果不抽取出来将会被打包在vendor当中,导致vendor每次都要被用户重新加载。抽离的配置写在optimization属性中的runtimeChunk配置中:

    optimization: {
        runtimeChunk: {
            name: 'manifest',
        },
    }
    复制代码

    1.5 webpack内部优化

    webpack4之前,内部优化主要使用两个插件:HashedModuleIdsPluginModuleConcatenationPlugin
    默认情况下,webpack会为每个模块用数字做为ID,这样会导致同一个模块在添加删除其他模块后,ID会发生变化,不利于缓存。
    为了解决这个问题,有两种选择:NamedModulesPluginHashedModuleIdsPlugin,前者会用模块的文件路径作为模块名,后者会对路径进行md5处理。因为前者处理速度较快,而后者打包出来的文件体积较小,所以应该开发环境时选择前者,生产环境时选择后者。
    ModuleConcatenationPlugin主要是作用域提升,将所有模块放在同一个作用域当中,一方面能提高运行速度,另一方面也能降低文件体积。前提是你的代码是用es模块写的。
    在 webpack4 中,只需要optimization的配置项中设置 moduleIdshashed或者named, 设置modeproduction即可。

    mode:'production',
    optimization : {
        moduleIds: 'hashed',
    }
    复制代码

    1.6 babel-polyfill优化

    目前本人项目里用的方法是命名一个来源于babel-polyfill的polyfill的文件,但是注释掉了大部分的import,仅保留项目的基本需求,并在在项目入口文件中引入。

    // webpack 中配置
    entry: {
      polyfill: path.join(process.cwd(), 'path/to/your/polyfill'),
    },
    复制代码

    参考下别人一些对polyfill优化的的优秀文章:

    2.参考文章

    webpack4——SplitChunksPlugin使用指南
    多页应用 Webpack4 配置优化与踩坑记录
    webpack 配置笔记 (这是我同事的blog哈哈,里面有我们现在使用的Webpack的具体配置,大家感兴趣可以去里面仔细看看学习,他是个高手,大家可以多多关注~)

    3. 结语

    上面的优化是基于对webpack有一定了解的情况下进行的,若你对webpack还不是很了解,我推荐到 webpack中文文档 里学习基础知识,并且到掘金上面搜索更多关于webpack的优秀文章啦!

    展开全文
  • 首先需要了解: 1、antd 依赖于模块[“react”, ...方式一:按需引入部分antd并按组件分离打包 希望得到的结果是将antd按组件加载,减少首屏加载的包大小; antd 又依赖于相应的rc模块,所以,rc同样按功能组分离,...

    方式一:按需引入部分antd并按组件分离打包

    希望得到的结果是将antd按组件加载,减少首屏加载的包大小;
    在这里插入图片描述

    antd 又依赖于相应的rc模块,所以,rc同样按功能组分离,
    同时antd->moment->local->各种语言包存在依赖关系
    统计结果:
    首屏加载 js: 769Kb 个数:34

    bundle antd rc moment local common 其他 合计
    307.23Kb 154.95Kb 454.95Kb 104.05Kb 106.85Kb 157.67Kb 219.58 1.47M

    如果在按需引入antd的timer-picker等时间相关的组件时,会同时加载moment的/locale的语言库,在我当前的场景中我只是用了中文,所以这部分开销几乎都是浪费的

    方式二:外链引入antd

    方式在这里插入图片描述
    统计结果:
    首屏加载 js: 987Kb 个数:11

    bundle common antd moment local 其他 合计
    297.92Kb 15.13Kb 1.11Mb 50.5Kb 3.77Kb 186.83Kb 1690.79Kb

    如果选择加载所有的antd组件,local 可以做按需加载了,但是未使用到的组件就会在首次加载时全部加载,存在一部分宽带浪费;

    方式三:将按需将部分ant及其依赖打包至common.js

    在这里插入图片描述
    统计结果:
    首屏加载js: 868Kb 个数:8

    bundle common 其他 合计
    298.01Kb 819.08Kb 347.22Kb 1.43M

    同样存在会同时加载moment的/locale的语言库的浪费

    对比结果:

    方式一 (非全量) 方式二(全量) 方式三(非全量)
    包总大小 1.47M 1.65Mb 1.43M
    antd相关 609.9Kb 1.11Mb 596.82Kb
    首屏加载js 769Kb 987Kb 868Kb
    首屏加载个数 34 11 8

    其他知识点
    1、antd 依赖于模块[“react”, “react-dom”, “moment”,“rc”]
    2、antd 的版本分为 antd(308kb) 和 antd-with-local(425kb) 两个版本

    展开全文
  • webpack.base.conf.jswebpack.dev.conf.jswebpack.prod.conf.js 一开始在接触webpack 的时候,简直痛不欲生,现在回头看,做个注释, 当然参考了很多文章。这是一个关于vue 开发的webpack 架构会列举出来 webpack...
  • webpack性能优化

    千次阅读 2017-08-01 01:39:41
    webpack无疑是强大的,强大到没有朋友,webpack的设计初衷也是伟大的,它可以编译打包我们的代码,借助loader,使得我们可以使用各种es6/es7的特性,可以使用sass/less,可以编写react代码等等。
  • 关于网友提出的“ webpack build后生成的app、vendor、manifest三者有何职能不同?”问题疑问,本网通过在网上对“ webpack build后生成的app、vendor、manifest三者有何职能不同?”有关的相关答案进行了整理,供...
  • webpack引入jquery插件失败的解决办法

    千次阅读 2017-09-17 18:31:40
    webpack项目中引入jquery插件jstree时,提示如下错误:TypeError: __WEBPACK_IMPORTED_MODULE_3_jquery___default(...)(...).jstree is not a function at a.mounted (list.vue:104) at _e (vue.min.js:6) at ...
  • vue开发,现在大部分做的都是(SPA)应用,但是,由于,需求不同,我们针对的用户需求变更较为,频繁,如果每次都全量打包更新,给开发的自测,及测试妹子的任务就会多,每次都要重新验证一下才放心。所以,想着能不...
  • 彻底解决Webpack打包性能问题 1 年前 这几天写腾讯实习生 Mini 项目的时候用上了 react 全家桶,当然同时引入了 Webpack 作为打包工具。但是开发过程中遇到一个很棘手的问题就是,react 加上 react-router...
  • gulp & webpack整合,鱼与熊掌我都要!

    千次阅读 2016-09-20 09:57:50
    为什么需要前端工程化?... 前端工程化的意义在于让前端这个行业由野蛮时代进化为正规军时代,近年来很多相关的工具和概念诞生。好奇心日报在进行前端工程化的过程中,主要的挑战在于解决如下问题: ...
  • Webpack 按需打包 Loadsh

    2019-11-07 14:08:53
    在数据操作时,我们经常会用的 loadsh 封装好的一些工具方法,但是并不想把整个包打包进项目里面。 以下提供几个按需打包 lodash 的方法。 使用方法: import {isEmpty, isObject, cloneDeep} from 'lodash'; ...
  • 昨天用webpack打包Vue的项目时,node内存溢出而停止build项目,即是项目构建过程中频繁报内存溢出:FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - process out of memory。并且打包速度相当慢,估计项目过...
  • 写在前面: 参考了许多资料,都差不多的,但是并不是很全,过程有点头疼 项目前提: index.html文件(在主目录下的) <!DOCTYPE html> <html lang="zh-CN"> <head>...m...
  • webpack配置常用部分有哪些

    千次阅读 2017-07-06 16:59:27
    webpack的配置文件是一个node.js的module,用CommonJS风格来书写,形如: module.exports = { entry: "./entry", output: { path: __dirname + "/dist", filename: "bundle.js" } } webpack的配置文件并没有...
  • 之前一直对webpack只是了解到一些皮毛,最近抽空学习了一些持久化缓存的必要性以及方案,并自己进行了一次从0到1的项目配置,在此分享一下,方便大家一起交流学习,有写错或理解错的地方还请大佬多多指点。...
  • node内存溢出而停止build项目,即是项目构建过程中频繁报内存溢出:FATAL ...并且打包速度相当慢,估计项目过大了。 解决方案一:通过 package.json 中的 "build" 加大内存 /* package.json 文件 */ "scripts"...
  • webpack

    2018-02-28 15:01:26
    转自:https://github.com/hawx1993/tech-blog/issues/3背景在去年年末参与的一个项目中,项目技术栈使用react+es6+ant-design+webpack+babel,生产环境全量构建将近三分钟,项目业务模块多达数百个,项目依赖数千个...
  • antd配置config-overrides.js文件

    千次阅读 2020-02-28 16:43:03
    下载依赖包(定义组件按需求打包) npm install react-app-rewired customize-cra babel-plugin-import 自定义less-loader,改变antd默认样式 npm install less less-loader 根目录定义加载按需打包的js配置模块: ...
  • webpack基本配置项总结

    千次阅读 2017-09-15 16:28:34
    webpack是一个用于web项目的模板打包工具。在大部分的使用场景中,我们将它看作是一个web前端模块打包工具,它将资源的本身当做模块,这些模块可以被导入和操作,最后打包到指定的文件中下面详细讲解各个配置项的...
1 2 3 4 5 ... 20
收藏数 448
精华内容 179
关键字:

webpack 全量打包 曾量打包