webpack学习笔记--优化

前言

了解了webpack的基本配置以后,接下来应该关注其优化策略。webpack的优化策略对咱们的程序有着极大的性能提高。这是我记录学习webpack优化的文章,纪录的同时也但愿分享给你们。css

DLL动态连接库

在开发的过程当中,咱们会引入像reactreact-dom这样的库,这样的库基本上每一次打包时它们的内容都不会改变,因此咱们引入动态连接库。将它们打包一次,在以后的构建过程当中它们就不会被打包,打包的模块也会使用动态连接库里面的代码而不是去node_modules中取,这样咱们的构建速度就会大大提高。下面让咱们来看看webpack中怎么构建动态连接库。html

打包

咱们新建一个webpack.dll.config.js的文件,配置以下node

const path = require('path')
const DllPlugin = require('webpack/lib/DllPlugin')
module.exports = {
    entry:{
        //将react、react-dom放到动态连接库中
        react:['react','react-dom']
    },
    output:{
        //输出的文件名称,[name]指的是当前动态连接库的名称,即react
        filename:'[name].dll.js',
        //输出到dist目录下
        path:path.resolve(__dirname,'dist'),
        //存动态连接库的全局变量名称,即_dll_react,加上_dll_防止全局变量冲突
        library:'_dll_[name]',
    },
    plugins:[
        new DllPlugin({
            //动态连接库的全局变量名称,须要和library一致
            name:'_dll_[name]',
            path:path.join(__dirname,'dist','[name].manifest.json')
        })
    ]
}
复制代码

下面执行命令npx webpack --config webpack.dll.config.js,dist目录下多了两个文件,分别是react.dll.jsreact.manifest.json react.dll.js里面包含React的基础运行环境,即reactreact-dom模块。react.manifest. json用于描述在动态连接库文件中包含哪些模块。react

而后再新建一个webpack.config.js文件,在打包出来的chunk块中声明须要引入的动态连接库,具体配置以下webpack

const path = require('path')
const DllReferencePlugin = require('webpack/lib/DllReferencePlugin')
module.exports = {
    entry: {
        main: './main.js'
    },
    output:{
        filename:'bundle.js',
        path:path.resolve(__dirname,'dist')
    },
    module:{
        rules:[

        ]
    },
    plugins:[
        new DllReferencePlugin({
            manifest:require('./dist/react.manifest.json')
        })
    ]
}
复制代码

执行命令npx webpack,在dist目录下生成bundle.jsweb

引入

而后咱们在dist目录下新建一个index.html文件,引入打包构建出来的文件和动态连接库。json

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    
    <script src="./react.dll.js"></script>
    <script src="./buncld.js"></script>
</body>
</html>
复制代码

HappyPack

当文件数量变多时,webpack构建速度慢的问题会变得特别明显。可是运行在node之上的webpack是单线程的,不能同时处理多个任务。而HappyPack可让webpack作到这一点,它将任务分解成多个子进程去并发执行。因为JavaScript是单线程模型,因此想要发挥多核CPU的做用只能经过多进程而不能经过多线程来实现。 接入HappyPack的代码以下浏览器

const path = require('path')
const HappyPack = require('happypack');
module.exports = {
    entry: {
        main: './main.js'
    },
    output: {
        filename: '[name].js',
        path: path.resolve(__dirname, 'dist')
    },
    module: {
        rules: [{
                test: /\.js$/,
                //以babel为id,转交给happypack处理
                use: ['happypack/loader?id=babel'],
            },
            {
                test: /\.css$/,
                //以css为id,转交给happypack处理
                use: ['happypack/loader?id=css']
            }

        ]
    },
    plugins: [
        new HappyPack({
            id: 'babel',
            loaders: ['babel-loader']
        }),
        new HappyPack({
            id: 'css',
            loaders: ['style-loader','css-loader']
        })
    ]
}
复制代码

执行构建命令 npx webpack 从命令行的输出能够看出HappyPack已经生效bash

Happy[babel]: Version: 5.0.1. Threads: 3
Happy[babel]: All set; signaling webpack to proceed.
Happy[css]: Version: 5.0.1. Threads: 3
Happy[css]: All set; signaling webpack to proceed.
复制代码

压缩代码

为了提高网页的加载速度,能够对资源进行压缩。服务器

压缩JavaScript

这里咱们会用到UglifyJS,它经过去掉无效代码、去掉日志输出、缩短变量名,从而来优化咱们的代码。 简单的配置以下

const UglifyJSPlugin = require('webpack/lib/optimize/UglifyJsPlugin')
module.exports = {
    //以上省略。。。
    plugins: [
        //压缩输出的 JavaScript 代码
        new UglifyJSPlugin({
            compress: {
                //在 UglifyJS 删除没有用到的代码时不输出警告
                warnings: false,
                //删除全部 console 语句, 能够兼容IE浏览器
                drop_console: true,
                //内嵌己定义可是只用到一次 的变量
                collapse_vars: true,
                //提取出现了屡次可是没有定义成变量去 用的静态值
                reduce_vars: true,
                output: {
                    //最紧凑的输出
                    beautify: false,
                    //删除全部注释
                    comments: false,
                }
            }
        })
    ]
复制代码

压缩CSS

CSS也能够向JavaScript同样被压缩,这里用到的工具是cssnanocssnano的意义不单单是删除空格,它能够理解CSS代码。例如 margin:10px 20px 10px 20px 会被压缩为 margin:10px 20px 基本配置以下

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const ExtractTextPlugin = require('extract-text-plugin')
module.exports = {
    //以上省略。。。。
    module: {
        rules: [{
            test: /\.css$/,
            use: [ExtractTextPlugin.extract({
                use: ['style-loader', 'css-loader?minimize']
            })]
        }]
    },
    plugins:[
        new HtmlWebpackPlugin({
            template:'./index.html',
            filename:'index.html'
        }),
        new ExtractTextPlugin({
            filename: '[name]_[contenthash:8].css'
        })
    ]
}

复制代码

提取公共代码

若是将多个页面的公共代码抽离成单独的文件,就能优化一些问题。例如相同的资源被重复加载,浪费用户的流量和服务器的成本。每一个页面要加载的资源太大,致使网页首屏加载缓慢,影响用户体验。 基本配置以下,此配置主要针对多页面。单页就不存在于公共代码这一说法了。

import 'react'
import 'react-dom'
import './index.css' //每一个页面都用到的样式
const CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin')
module.exports = {
    module: {
        entry: './main.js',
        rules: [{
            test: /\.css$/,
            use: [ExtractTextPlugin.extract({
                use: ['style-loader', 'css-loader?minimize']
            })]
        }]
    },
    plugins: [
        new CommonsChunkPlugin({
            //从已有的common和base两个现成的chunks中提取公共部分 
            chunks: ['common', 'base'],
            //将公共部分放到base中 这样配置以后 common会变小,由于公共部分都跑到了base里,而base不变
            name: 'base'
        })
    ]
}
复制代码

为了能使网页运行,以网页A为例,除了打包出来的A页面的JavaScript代码还需引入公共部分代码

<script src= 'base.js'></script>
<script src='common.js'></script>
<script src='a.js'></script> 
复制代码

按需加载

单页应用首次渲染缓慢,一个很重要的缘由是一次性加载了全部功能对应的代码。这个时候若是采用按需加载,咱们网站的性能将会大大提高。 在webpack里,按需加载能够这样来写。例如咱们只打包出了一个bundle.js。在bundle.js中,有这么一段代码

window.document.getElementById('button').addEventListener('click',()=>{
    import('./show').then(show=>{
        show('webpack')
    })
})
复制代码

show.js

module.exports= function (content) {
    window.aleat(`hello ${content}`)
}
复制代码

webpack中内置了import语句的支持,当遇到这样的语句时,首先会生成一个新的chunk,而后触发import的时候再去加载这个chunk,返回的是一个Promise对象,在加载成功时使用then方法进行下面的操做,为了让webpack正确打包chunk,配置文件中需加入

output:{
    //从entry打包生成的chunk
    filename:'[name].js',
    //动态加载生成的chunk
    chunkFileName:'[name].js'
}
复制代码

最后

webpack的优化配置还有不少,这里只记录了我平时经常使用的,具体详情还请查阅官方文档。

相关文章
相关标签/搜索