30

react 配合 webpack 打包固然好用,但比较尴尬的是打包过后的 react 文件的体积……

首屏加载过慢,怎么办?慢慢优化呗……
一般正常的网站首屏应该在1s左右加载出来,这个体验性简直极好的。
既然优化那就先从资源文件大小开始。
可能有的人会说既然优化,那就做个按需。这确实是个好主意,但是如果你打包后的文件不是很大的话,其实没必要做按需。

首先配置全局变量

告诉 webpack 我要发布 production 了,按照 production 方式去打包。

   new webpack.DefinePlugin({
        'process.env': {
            //注意一个单引号一个双引号…… 这里是要将 "production" 替换到文件里面
            NODE_ENV: '"production"'
        }
    })

1. 注意 devtool 中的 source-map。

如果你打包后的文件莫名其妙的好几 MB的大小…… 看到这个文件心里真是一万只奔腾的……

如果好几 MB, 那不用想了肯定是 source-map 的问题, 注意 source-map 的那种几种类型使用.

webpack sourcemap 选项多种模式的一些解释
https://webpack.github.io/docs/configuration.html#devtool

source map 在开发调试的时候确实是好用,但也只是开发的时候……
生产环境没多大必要去用这个了,当然也有人选择在生产环境开启 source-map ,方便调试, 但我觉得真心没必要, 在生产环境调试的方法多的是,没必要用这个方式.

可以试一下,当开启 devtool打包后的文件

devtool: "inline-source-map"

打包后3.9MB...

瞬间高潮了,这个js挂在服务器上没有10s出不来的,记得当我第一次在服务器上打包后,满怀期待的打开页面后的场景……

其实了解下 source-map 的不同方式就知道了, inline-source-map 为每一个文件添加 sourcemap 的 DataUrl,注意这里的文件是打包前的每一个文件而不是最后打包出来的,同时这个 DataUrl 是包含一个文件完整 souremap 信息的 Base64 格式化后的字符串,而不是一个 url。

建议在production环境打包的时候关闭 devtool.

如果非得在线上使用 source-map, 可以配置为

devtool: "#source-map",

这样只会在文件后面跟一个 url,这样对源文件影响就很小了

这样还有1.52MB

可以看到使用#source-map后 vendor.js 已经从3.9M 减到 1.52MB。
如果非要在生成环境使用 source-map, 请严谨选择。

2. 使 css 剥离 js 文件, 将 css 单独打包。

依赖插件 npm install --save-dev extract-text-webpack-plugin 先安装再使用

    var ExtractTextPlugin = require('extract-text-webpack-plugin');
    
    //在 plugins 中配置
    plugins: [ new ExtractTextPlugin('[name].[contenthash].css') ]

把 css 单独打包出来,免得以后只修改 css 导致 浏览器端 js 的缓存也失效了。
这里使用了 contenthash, webpack 会按照内容去生成 hash 值。

3. 压缩, 去除注释

注意如果开启了source-map选择inline-source-map压缩后依然好几MB的

    //在 plugins 中添加
    new webpack.optimize.UglifyJsPlugin({
        comments: false,        //去掉注释
        compress: {
            warnings: false    //忽略警告,要不然会有一大堆的黄色字体出现……
        }
    })

最好开启去掉代码注释。
代码压缩后提升简直不是一点两点的……

压缩后只有410kb

哇塞很赞哎. 其实还是不行的,这样首屏加载还会慢点, 怎么办 gzip 咯。

4. 开启 gzip 压缩

依赖插件 npm install --save-dev compression-webpack-plugin

git 地址:compression-webpack-plugin

    var CompressionWebpackPlugin = require('compression-webpack-plugin');

    //在 plugin 中添加
    new CompressionWebpackPlugin({ //gzip 压缩
        asset: '[path].gz[query]',
        algorithm: 'gzip',
        test: new RegExp(
            '\\.(js|css)$'    //压缩 js 与 css
        ),
        threshold: 10240,
        minRatio: 0.8
    })

这个就很满意……

只有115KB了

gzip

这个截图是请求服务器上的 js。之前这个 js 要10多秒的……(云服务器最低配置的那种)
请求截图

从3.9MB 到 115KB!!! 真是极好的。

5. 压缩 html, 自动添加上面生成的静态资源。

依赖插件 npm install --save-dev html-webpack-plugin

git 地址:html-webpack-plugin

    var HtmlWebpackPlugin = require('html-webpack-plugin');
    
    new HtmlWebpackPlugin({
        filename: 'react.html',    //生成的文件,从 output.path 开始 output.path + "/react.html"
        template: '../client/react.html',  //读取的模板文件,这个路径是相对于当前这个配置文件的
        inject: true, // 自动注入
        minify: {
            removeComments: true,        //去注释
            collapseWhitespace: true,    //压缩空格
            removeAttributeQuotes: true  //去除属性引用
            // more options:
            // https://github.com/kangax/html-minifier#options-quick-reference
        },
        //必须通过上面的 CommonsChunkPlugin 的依赖关系自动添加 js,css 等
        chunksSortMode: 'dependency'
    })

这样就大功告成了, css,js 开启 gzip 压缩后, 会将生成的文件名自动注入到 html 中。 如果有多个 html 配置再添加一个 new HtmlWebpackPlugin() 即可。

小结

  1. 确定不会在生产环境打包多余的代码, 比如 热加载 只是举个例子

  2. 检查只在 dev 使用的配置,在生产环境将其去掉. 可使用配置文件,灵活配置,灵活切换

  3. 去除所有注释, 压缩所有可压缩的资源文件.

  4. 开启 gzip压缩.

总而言之为了让文件变小,为了让浏览器加载的更快,我们真的要无所不用其极……

以上, 致那颗骚动的心……

悠扬小Q
2.3k 声望31 粉丝

编程5分钟,扯蛋俩小时。 最近出差比较忙,向邀请我回答的同学说声抱歉。。。没太多时间回复了。。。