重构之路:webpack打包体积优化(超详细)

栏目: CSS · 发布时间: 5年前

内容简介:这一章讲打包体积优化,这个也算是最重要的一章了,我之前可是花了很多时间去查资料怎么优化打包体积的,不同版本的webpack之间还有一些区别,所以也算踩了很多的坑,所以这一章会比较长。这边我大概写了一下页面具体布局,是下面这样的:我们再去看一下打包体积,有2.75M,已经算很大了:

这一章讲打包体积优化,这个也算是最重要的一章了,我之前可是花了很多时间去查资料怎么优化打包体积的,不同版本的webpack之间还有一些区别,所以也算踩了很多的坑,所以这一章会比较长。

这边我大概写了一下页面具体布局,是下面这样的:

重构之路:webpack打包体积优化(超详细)

我们再去看一下打包体积,有2.75M,已经算很大了:

重构之路:webpack打包体积优化(超详细)

我们使用一个打包可视化的插件来看看都有什么被打包进去了,我们执行:

yarn add webpack-bundle-analyzer -D
复制代码

在webpack.config.prod.js的plugins里添加一行,注意端口可以修改,别冲突了:

new BundleAnalyzerPlugin({ analyzerPort: 8081 })
复制代码

修改完成后,执行yarn run build命令,在浏览器弹出窗口,我的是这样的:

重构之路:webpack打包体积优化(超详细)

可以清晰的看到antd和react-dom就占了一半多,下面来优化。

1. 修改mode

我们去webpack.config.prod.js里:

//mode:'development'
mode:'production' //修改成开发环境
复制代码

然后查看打包体积,瞬间减少了一半多,修改成开发环境webpack会自动的去优化包体积,比如压缩代码之类的:

重构之路:webpack打包体积优化(超详细)
重构之路:webpack打包体积优化(超详细)

2. antd按需加载

在控制台执行:

yarn add babel-plugin-import -D
复制代码

然后去webpack.config.common.js配置:

plugins:[
               	"@babel/plugin-transform-runtime",
                 ['import',{
                     libraryName:'antd',
                     libraryDirectory: 'es',
                     style:true
                 }]
             ]
复制代码

在less的配置里修改:

{
         loader:'less-loader',
           options:{
              javascriptEnabled: true
           }
    }
复制代码

然后我们去使用到antd组件的地方,修改成以下这样的形式引入:

// import Col from 'antd/lib/col';
// import Row from 'antd/lib/row';
// import "antd/dist/antd.css"; //css也去掉
import {Col,Row} from 'antd'
复制代码

再执行打包命令,变成601kb:

重构之路:webpack打包体积优化(超详细)
重构之路:webpack打包体积优化(超详细)

3. mini-css-extract-plugin提取css

我们使用mini-css-extract-plugin来将css从js里分离出来。在控制台执行:

yarn add mini-css-extract-plugin -D
复制代码

在webpack.config.prod.js里配置:

//在顶部引入
const MiniCssExtractPlugin=require('mini-css-extract-plugin');

//在plugins里添加
new MiniCssExtractPlugin({//提取css
            filename:'css/main.css'
        }),
复制代码

这样我们可以将css单独分离到css文件夹里。然后再打包看看:

重构之路:webpack打包体积优化(超详细)
重构之路:webpack打包体积优化(超详细)

我们发现js包变小,css也被分离出来了,但是css居然有223kb,打开css文件,我们发现css没有被压缩掉。

我们在控制台执行,这两个插件前者是压缩css的,后者是压缩js的,本来在生产环境下会压缩js的,但是使用optimize-css-assets-webpack-plugin会导致压缩js无效,所以我们需要额外引入一个压缩js的插件:

yarn add optimize-css-assets-webpack-plugin uglifyjs-webpack-plugin -D
复制代码

我们在webpack.config.common.js里配置:

//这个配置和module,plugins是同级的
optimization:{
        minimizer:[
            new UglifyJsPlugin({//压缩js
                cache:true,
                parallel:true,
                sourceMap:true
            }),
            new OptimizeCSSAssetsPlugin()//压缩css
        ]
    },
复制代码

然后我们去打包,我们发现css已经变小了:

重构之路:webpack打包体积优化(超详细)

4. DllPlugin和DllReferencePlugin

在之前的打包图我们可以看见包体积大部分是被react全家桶和babel占用了,现在我们把这些给拿出来单独放到一个js文件里,因为这些东西我们是不会去改变它的。

我们在根目录下新建一个==webpack.config.dll.js==,然后在里面配置,因为DllPLugin是webpack下的,所以我们不用下载:

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

//只需要使用yarn run dll一次就行
module.exports={
    mode:'production',
    entry:{
    	//这里把react方面的东西和babel放到这里
        vendor:['react','react-dom','react-router-dom']
    },
    output:{
        filename:'dll/_dll_[name].js',
        path:path.resolve(__dirname,'dist'),
        library:'_dll_[name]'
    },
    plugins:[
        new webpack.DllPlugin({
            name:'_dll_[name]',
            path:path.resolve(__dirname,'dist/dll','mainfist.json')
        }),
        new CleanWebpackPlugin(['./dist/dll']),//删除dll目录下的文件
    ]
}
复制代码

再去==webpack.config.common.js==里配置:

//在plugins下新增
new webpack.DllReferencePlugin({
     manifest: path.resolve(__dirname, 'dist/dll', 'mainfist.json')
}),
复制代码

然后去package.json.里配置:

//在scripts下面新增一条这个
"dll": "webpack --config webpack.config.dll.js"
复制代码

在控制台执行:

yarn run dll
复制代码
重构之路:webpack打包体积优化(超详细)

我们发现已经被打包出来了,我们还需要去public/index.html进行引入:

//在body最后新增
<script src="dll/_dll_vendor.js"></script>
复制代码

然后去执行yarn run build:

重构之路:webpack打包体积优化(超详细)
重构之路:webpack打包体积优化(超详细)

文件大小又变小了。

5. @babel/polyfill

我们在之前的图里可以看见,core-js占用了很大的一部分体积,这个就是babel/polyfill使用的库。这里我提供两种方法。

1.@baebl/polyfill按需加载

我们可以使用useBuiltIns这个属性,这个属性是babel7新增的,我们需要这样配置:

presets:[
    [
        '@babel/preset-env',
        {
            "targets": {
                "browsers": [
                    "ie >=9",
                    "last 2 version",
                    "> 5%",
                    "not dead"
                ]
            },
            "useBuiltIns":"usage"
        }
    ],
    '@babel/preset-react'
],
复制代码

当我们这样配置之后,我们就可以把index.js顶部的

//import '@babel/polyfill'  //可以去掉这一行了
复制代码

然后我们再打包,执行yarn run build:

重构之路:webpack打包体积优化(超详细)
重构之路:webpack打包体积优化(超详细)

这个时候打包体积变成了132kb,但是我在使用这种方法的时候,在ie11下可以正常显示,在ie10及以下就出现下面的错误了,:

重构之路:webpack打包体积优化(超详细)

目前我还没找到解决方法,有解决方法的麻烦也跟我说一下,谢谢了。如果你不需要兼容ie10或以下的话可以使用这种方法。

2.提取@baebl/polyfill

第二种方法,我们可以直接提取@babel/polyfill,就像react全家桶一样。我们去==webpack.config.dll.js==里配置:

//添加@babel/polyfill
vendor:['react','react-dom','react-router-dom','@babel/polyfill']
复制代码

然后去index.js的顶部添加:

import '@babel/polyfill'
复制代码

然后我们去执行yarn run dll,可以看见vendor的包变大了:

重构之路:webpack打包体积优化(超详细)

然后我们执行yarn run build:

重构之路:webpack打包体积优化(超详细)
重构之路:webpack打包体积优化(超详细)

我们发现包体积和之前的方法差不多,然后我们去ie下看看:

重构之路:webpack打包体积优化(超详细)

只有在==ie8==下会出现这样的错误,ie9及以上都是正常显示的,兼容性算是很不错了,所以这两种方法如何取舍就看自己项目需不需要兼容ie了。

6. react-router动态加载(react组件懒加载)

之前我们是全部的组件都在页面上加载出来,这样我们还没点击的组件也会加载,这样就导致浪费了。我们使用动态加载来让点击到的组件才进行加载就好多了。

我们在控制台执行:

yarn add react-loadable babel-plugin-syntax-dynamic-import -D
复制代码

如何在==webpack.config.common.js==里配置:

plugins:[
    "@babel/plugin-transform-runtime",
    'babel-plugin-syntax-dynamic-import',//增加这一行
    ['import',{
        libraryName:'antd',
        libraryDirectory: 'es',
        style:true
    }]
]
复制代码

然后我们去使用路由的地方修改:

import Loadable from 'react-loadable';//注意要加上这一行
// import A from '../pages/A/A'
// import B from '../pages/B/B'

//修改成这样子的写法
const A = Loadable({
    loader: () => import('../pages/A/A'),
    loading:()=> {
        return <div>Loading...</div>
    }
});
const B = Loadable({
    loader: () => import('../pages/B/B'),
    loading:()=> {
        return <div>Loading...</div>
    }
});
复制代码

再去执行打包命令,然后查看:

重构之路:webpack打包体积优化(超详细)
重构之路:webpack打包体积优化(超详细)

我们发现包体积变大了,这是因为我现在项目没写什么东西,所以引入了插件后,包就变大了,在组件写多了之后,这个动态加载能减少很多的体积。

我们可以来看一下效果:

页面刚加载的时候是这样的

重构之路:webpack打包体积优化(超详细)

点击一个路由后变成这样:

重构之路:webpack打包体积优化(超详细)

可以看见动态的加载了一个js文件。

index.js体积解释

这里再说一下打包的图,其实我在src下写的代码很少,但是打包图的这里有个index.js却有将近90kb大,这是为什么?其实这个是antd按需加载打包进来的组件,我们可以试一下,这个是我现在主页上大部分使用到的antd组件代码:

<div>
    <Header/>
    <Row>
        <Col xs={24} sm={24} md={6} lg={4} xl={4} xxl={4}>
            <Aside/>
        </Col>
        <Col xs={24} sm={24} md={18} lg={20} xl={20} xxl={20}>
            <div className="content">
                {this.props.children}
            </div>
        </Col>
    </Row>
</div>
复制代码

我们将使用到的antd组件都注释掉,只留下Header:

//import {Col,Row} from 'antd'

<div>
    <Header/>
    {/*<Row>*/}
        {/*<Col xs={24} sm={24} md={6} lg={4} xl={4} xxl={4}>*/}
            {/*<Aside/>*/}
        {/*</Col>*/}
        {/*<Col xs={24} sm={24} md={18} lg={20} xl={20} xxl={20}>*/}
            {/*<div className="content">*/}
                {/*{this.props.children}*/}
            {/*</div>*/}
        {/*</Col>*/}
    {/*</Row>*/}
</div>
复制代码

然后我们再去打包:

重构之路:webpack打包体积优化(超详细)
重构之路:webpack打包体积优化(超详细)

现在src下的这个包已经变的很小了。

7. splitChunks

然后我们将antd之类的第三方库从主要的包里分离出来。

我们在==webpack.config.common.js==里的optimization里配置,在和之前我们写js和css压缩的==minimizer==的同级的地方:

splitChunks:{
    cacheGroups:{
        vendors:{//node_modules里的代码
            test:/[\\/]node_modules[\\/]/,
            chunks: "initial",
            name:'vendors', //chunks name
            priority:10, //优先级
            enforce:true 
        }
    }
}
复制代码

然后再去执行打包命令:

重构之路:webpack打包体积优化(超详细)
重构之路:webpack打包体积优化(超详细)

我们可以发现关于antd的js和css都被抽离出来了,chunk Names为vendors的就是,而为main的就是我们自己写的代码,我们自己写的其实很少。

虽然antd的组件比较大,但它们只会打包一次,而且在服务端配置gzip的情况下,体积又可以减少三分之一多,还是可以接受的。

结尾

最后我们将主包体积从2.75M优化到5kb左右,但其实我们是将一个大的包拆分成多个小包,并提取公共代码。

这里其实还有一个使用externals的优化方法,然后使用CDN引入,但我这边已经使用了DllPlugin了,就不使用那种方法了,两种方法大家可以合理使用。

这一章写了太多的东西了,而且稍微有点杂,但是应该也算是挺详细了,但是我觉得webpack打包体积优化的还不止这些,如果你们还有其他能优化的方法,也和我说一下,谢谢了。

(ps:如果文章哪里有错误,请在评论指出,谢谢)


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Clean Architecture

Clean Architecture

Robert C. Martin / Prentice Hall / 2017-9-20 / USD 34.99

Practical Software Architecture Solutions from the Legendary Robert C. Martin (“Uncle Bob”) By applying universal rules of software architecture, you can dramatically improve developer producti......一起来看看 《Clean Architecture》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具