当前位置:首页 » 《休闲阅读》 » 正文

webpack 优化_y_w_x_k的博客

7 人参与  2022年01月28日 13:59  分类 : 《休闲阅读》  评论

点击全文阅读


1.热模块更新

webpack.config.js设置:

entry : ['./src/js/index.js','./src/index.html'],

入口文件inde:x.js监听非入口js文件:

if(module.hot){
    module.hot.accept("./print.js",function(){
        echo()
    })
}

if(module.hot){
    module.hot.accept("./test.js",function(){
        test1
    })
}

2.开发环境代码映射source-map

devtool : 'source-map'
//外部映射:生成额外map文件,内部映射:映射代码写在built.js文件内
//source-map 外部映射,显示错误代码准确信息和详细位置
//inline-source-map 内联映射,显示错误代码准确信息和详细位置
//hidden-source-map 外部映射, 显示错误代码准确信息,显示构建后错误代码位置,不显示源代码错误位置
//eval-source-map 内联映射, 显示错误代码准确信息,显示构建后错误代码位置,显示源代码错误位置(在文件hash值冒号后面),源代码文件会加hash值
//nosources-source-map 外部映射,显示错误代码准确信息和详细位置,不显示任何源代码
//cheap-source-map 外部映射,显示错误代码准确信息和详细位置,只精确到一整行
//cheap-module-source-map 与cheap-source-map类似,会将loader的source-map加入
//速度 eval>inline>cheap...    eval-cheap-source-map最快,适合开发环境
//调试友好 source-map 
//开发环境最终选择 eval-source-map 或者 eval-cheap-module-source-map
//生产环境下,内联会让代码体积庞大,所以只选外部映射,可选source-map,考虑隐藏源代码可加hidden或者nosources

3.oneOf 

优化点: 每个不同类型的文件在loader转换时,遍历时会被module中rules中所有loader命中,设置oneOf后遍历时被一个loader命中的文件不会继续被其他loader命中,相当于break;利用了每个文件只能被一个loader转换;

当需要一个文件被多个loader转换时,在oneOf中保留一个loader配置,其他的放在oneOf外面即可,例如:

rules : [
            /*
                    *   正常情况一个文件只能被一个loader处理;
                    *   当一个文件被多个loader处理,一定要指定loader执行的先后顺序
                    *   先执行eslint,再执行babel    
                    */
            {
                //js语法规范检查,还需要在packge.json中配置eslintConfig,选择airbnb语法规范
                test : /\.js$/,
                exclude : /node_modules/,
                loader :"eslint-loader",     
                enforce : "pre",    //优先执行
                options : {
                    //自动修复语法不规范
                    fix : true
                }
            },
            {
                oneOf : [
                    {
                        test : /\.css$/,
                        use : [...commonCssLoader]
                    },
                    {
                        test : /\.less$/,
                        use : [ ...commonCssLoader,"less-loader" ]
                    },
                    
                    {
                        //es6新语法兼容性处理
                        test : /\.js$/,
                        exclude : /node_modules/,
                        loader : 'babel-loader',
                        options : {
                            presets : [
                                [
                                    //兼容简单的es6改进语法
                                    "@babel/preset-env",
                                    {
                                        //按需加载promise,await等新语法
                                        useBuiltIns : 'usage',
                                        corejs : { version : 3 },
                                        targets : {
                                            chrome : "60",
                                            firefox : "50",
                                            ie : "9",
                                            safari : "10",
                                            edge : "17"
                                        }
                                    }
                                ]
                            ]
                        }
                    },
                    {
                        //解析css内的图片
                        test : /\.(jpg|png|gif)$/,
                        generator : {
                            filename : 'imgs/[hash][ext]'
                        }
                    },
                    {
                        //解析html内的图片
                        test : /\.html$/,
                        use : ["html-loader"]
                    },
                    {
                        //解析其他文件
                        exclude : /\.(js|css|less|sass|html|jpg|png|gif)$/,
                        generator : {
                            filename : "media/[hash][ext]"
                        }
                    }
                ]  
            },
            
        ]

4.生产环境缓存配置

1.babel缓存,只更新改变的浏览器兼容代码,第二次打包的速度更快。

 {
                        //es6新语法兼容性处理
                        test : /\.js$/,
                        exclude : /node_modules/,
                        loader : 'babel-loader',
                        options : {
                            presets : [
                                [
                                    //兼容简单的es6改进语法
                                    "@babel/preset-env",
                                    {
                                        //按需加载promise,await等新语法
                                        useBuiltIns : 'usage',
                                        corejs : { version : 3 },
                                        targets : {
                                            chrome : "60",
                                            firefox : "50",
                                            ie : "9",
                                            safari : "10",
                                            edge : "17"
                                        }
                                    }
                                ]
                            ],
                            cacheDirectory : true
                        }
                    },

2.文件资源缓存,给每个编译文件加个hash值,文件内容变更的时候生成新的编译文件;

存在一个问题,所以文件共用一个hash值,当一个文件更新,其他文件全都会生产新的编译文件

output : {
        filename : "js/built[hash:10].js",
        path : resolve(__dirname,"build")
    },

plugins : [
        //以src/index.html文件为html模板文件
        new HttpWebpackPlugin({
            template : "./src/index.html",
            minify : {
                collapseWhitespace : true,  //压缩html内空格,
                removeComments : true   //去除html注释
            }
        }),
        new MiniCssExtractPlugin({
            filename : "css/built[hash:10].css"
        }),
    ],

chunkhash,如果编译文件来源于同一个chunk,那么他们的hash值是一样的,

chunk定义: 由于上面的例子中,index.css,print.css,test.css都在index.js中被引用,那么他们一个chunk;

所以上面的编译文件用chunkhash的话,当一个文件改变了,其他文件也会生成新的编译文件,因为他们是同一个chunk;

contenthash:根据文件内容生成hash值,不同文件的hash值不一样,当改变一个文件的内容,编译时其他文件不会产生影响;

output : {
        filename : "js/built[contenthash:10].js",
        path : resolve(__dirname,"build")
    },

plugins : [
        //以src/index.html文件为html模板文件
        new HttpWebpackPlugin({
            template : "./src/index.html",
            minify : {
                collapseWhitespace : true,  //压缩html内空格,
                removeComments : true   //去除html注释
            }
        }),
        new MiniCssExtractPlugin({
            filename : "css/built[contenthash:10].css"
        }),
    ],

让代码上线运行更快

5.tree shaking

去除无用代码

前提:1.必须使用es6模块化;2.必须是production环境

optimization: {
        //CSS压缩
        minimizer: [
            new CssMinimizerPlugin(),
        ],
        minimize: true,
    },

设置此选项貌似会默认设置开发环境,导致js代码不会压缩,tree-shaking无法执行

默认css文件会被当作无用文件尔不被执行,修改方法:packge.json配置:

"sideEffects" : ["*.css","*.less"]

6.code_split文件分割

拆分文件

1.拆分入口,单入口改多入口:

//多入口,有一个入口就生成一个bundle
    entry : {
        main : './src/js/index.js',
        test2 : './src/js/test2.js'
    },
    output : {
        //[name]根据入口文件名,生成bundle文件名
        filename : "js/[name][contenthash:10].js",
        path : resolve(__dirname,"build")
    },

单页面应用使用单入口,多页面应用使用多入口;

2.设置optimization:

将node_modules中的代码单独打包成一个chunk,如果是多入口共用同一个node_modules也只生成一个node_modules

optimization : {
        splitChunks : {
            chunks : "all"
        }
    },

3.在单入口应用下,分割文件

使用import方法引入文件:


import(/* webpackChunkName: 'test2' */"./test2.js").then(res=>{
  console.log(res.minus(8,1));
}).catch(err=>{
  console.log(err);
})

7.JS文件懒加载

懒加载:当文件需要时加载

预加载:会在js使用之前提前加载文件

document.getElementById("d1").onclick=function(){
  import(/* webpackChunkName:'test2', webpackPrefetch:true*/"./test2.js").then(res=>{
    console.log(res.minus(101,1)); 
  })
}

正常加载与预加载的区别:

正常加载可以认为是并行加载(同一时间加载多个文件),懒加载是等其他资源加载完毕,浏览器空闲后再加载其他资源

8.PWA-渐进式网络应用开发程序(离线可访问)

npm i workbox-webpack-plugin -D

webpack.config.js配置

const WorkboxWebpackPlugin=require("workbox-webpack-plugin")


plugins : [
        //以src/index.html文件为html模板文件
        new HttpWebpackPlugin({
            template : "./src/index.html",
        }),
        new WorkboxWebpackPlugin.GenerateSW({
            //帮助serviceworker快速启动
            clientsClaim : true,
            //删除旧的serviceworker,生成一个servicewoker配置文件
            skipWaiting : true
        })
    ],

入口文件index.js引入:

注意:需要在服务器环境运行

//注册serviceworker
//处理兼容性问题

if("serviceWorker" in navigator){
  window.addEventListener('load',()=>{
    //service-worker.js由webpack的workbox-webpack-plugin插件生成
    navigator.serviceWorker.register('./service-worker.js').then(()=>{
      console.log("sw registed success");
    }).catch(error=>{
      console.log("sw registed error",error);
    })
  })
}else{
  console.log("no support");
}

9.多进程打包

npm i thread-loader -D

在babel之后引入

有利有弊:进程启动需要600ms,进程通信也有开销;只有工作消耗时间比较长才需要多进程打包

module : {
        rules : [
            {
                //es6新语法兼容性处理
                test : /\.js$/,
                exclude : /node_modules/,
                use : [
                    //多进程打包
                    "thread-loader",
                    {
                        loader : 'babel-loader',
  
                    }
                ],
            }
        ]
    },

详细配置

rules : [
            {
                //es6新语法兼容性处理
                test : /\.js$/,
                exclude : /node_modules/,
                use : [
                    //多进程打包
                    {
                        loader : "thread-loader",
                        options : {
                            workers : 2     //2个进程
                        }
                    },
                    {
                        loader : 'babel-loader',
                    }
                ],
            }
        ]

10.externals

忽略打包项,不生成bundle,一般不将cdn(引用)文件打包成bundle,优化打包速度

    //与entry同级
    externals : {
        //忽略库名--npm包名
        jQuery : 'jQuery'
    }

11.dll单入口库文件单独打包

webpack.dll.js文件(与webpack.config.js同级):


/*
使用dll技术,对某些库(jquery,react,vue)进行单独打包,
当运行webpack时,默认查找webpack.config.js
需求:需要运行webpack.dll.js文件
webpack --config webpack.dll.js
*/

let {resolve}= require("path")
let Webpack=require("webpack")

module.exports={
    entry : {
        //最终打包生成的[name]--要打包的库名称
        jquery : ['jquery']
    },
    output : {
        filename : '[name].js',
        path : resolve(__dirname,"dll"),
        library:'[name]_[hash]',
    },
    plugins : [
        //打包生成mainfest.json,提供jquery映射
        new Webpack.DllPlugin({
            name : '[name]_[hash]',      //映射库的暴露内容的名称
            path : resolve(__dirname,"dll/mainfest.json")
        })
    ],
    mode : "production"
}

webpack.config.js:

npm i add-asset-html-webpack-plugin -D


const { resolve }=require("path")

const HttpWebpackPlugin=require("html-webpack-plugin")

let Webpack=require("webpack")
let AddAssetHtmlWebpackPlugin=require("add-asset-html-webpack-plugin")

module.exports={
    entry :  './src/js/index.js',
    output : {
        //[name]根据入口文件名,生成bundle文件名
        filename : "js/[name].js",
        path : resolve(__dirname,"build")
    },
    module : {
    
    },

    plugins : [
        //以src/index.html文件为html模板文件
        new HttpWebpackPlugin({
            template : "./src/index.html",
        }),
        //告诉webpack哪些库不参与打包,同时修改使用名称
        new Webpack.DllReferencePlugin({
            manifest : resolve(__dirname,'dll/mainfast.json')
        }),
        //将dll文件夹中某个文件打包输出出去,并在html中自动引入该资源
        new AddAssetHtmlWebpackPlugin({
            filepath : resolve(__dirname,'dll/jquery.js'),
            outputPath : "auto"
        })
    ],
    mode : 'production',     //生产环境js自动压缩
    devServer : {
        hot : true
    },
}


点击全文阅读


本文链接:http://zhangshiyu.com/post/34054.html

文件  打包  映射  
<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1