美文网首页网页前端后台技巧(CSS+HTML)前端笔记
webpack实战——生产环境配置【中】

webpack实战——生产环境配置【中】

作者: 流眸Tel | 来源:发表于2020-09-17 17:28 被阅读0次

    前言

    上一篇中,描述了一些关于生产环境的配置:环境变量的使用、配置文件描述、开启生产模式、环境变量自定义配置等,从这几个方面入手都可以对生产环境产生一些有利影响。

    那么本篇,从source map资源压缩方面入手,继续深入探究。

    1. source map

    source map 指的是将编译、打包、压缩后的代码映射回源代码的过程。

    经过webpack打包压缩后的代码基本上已经不具备可读性,此时若是代码抛出错误,想要回溯它的调用栈是非常困难的,而有了source map,加上浏览器调试工具(dev tools),要做到这一点就会变得很容易。同时,它对于线上问题的追查也有一定帮助。

    1.1 原理

    工作原理:webpack对于工程源代码的每一步处理都有可能会改变代码的位置、结构、甚至是所处文件,因此每一步都需要生成对应的source map。
    如果我们启用了devtool配置,那么source map就会跟随源代码一步步被传递,直到生成最后的map文件。这个文件默认就是打包后的文件名字上加上后缀[.map],例如bundle.js.map。

    在生成map文件的同时,bundle文件中会追加一句注释来标识map文件的位置,例如:

    // bundle.js
    (function() {
        // bundle的内容
        ...
    })()
    // # sourceMappingURL=bundle.js.map
    

    而当我们打开浏览器开发者工具后,其实map文件同时也会被加载进来,这时浏览器会使用它来对打包后的bundle文件来进行解析,分析出源代码的目录结构和内容。

    亲自尝试过的朋友可能会发现,打包后,map文件会比较大,甚至超出源文件几倍的体积大小,不过不用担心,不打开开发者工具是不会加载这些map文件的,因此对于普通用户来讲没有什么影响。但是要注意的是,虽然普通用户看不到,不过有经验的“特殊人群”还是可以通过dev tools看到工程源码的。因此建议如果是生产环境,还是要解决一下。如何解决呢?下面会提到。

    1.2 配置

    在webpack.config.js中添加devtool即可完成对source map的配置。

    // webpack.config.js
    module.exports = {
        // ...
        devtool: 'source-map'
    }
    

    而对于CSS、SCSS及Less来说,则需要添加额外的source map配置项。如:

    const path = require('path');
    module.exports = {
        // ...
        devtool: 'source-map',
        module: {
            rules: [
                // scss
                {
                    test: /\.scss$/,
                    use: [
                        'style-loader',
                        {
                            loader: 'css-loader',
                            options: {
                                sourceMap: true,
                            }
                        },
                        {
                            loader: 'sass-loader',
                            options: {
                                sourceMap: true
                            }
                        }
                    ]
                }
            ]
        }
    }
    

    webpack给出多种source map形式:

    • source-map
    • cheap-source-map
    • eval-source-map
    • ...

    在开发环境中,通常使用module-eval-source-map,因为在打包速度和源码信息还原程度都属于良好程度。

    而在生产环境中,通常我们会对代码进行压缩,而最常见的压缩插件UglifyjsWebpackPlugin目前只支持source-map形式。

    1.3 安全

    在1.1中我们抛出一个安全问题,就是在开启source-map的时候任何人都可以通过浏览器的开发者工具devtool来看到工程源码,因此对于安全性来讲是一个极大的隐患。那么如何能在保持其功能的同时又能防止暴漏源码呢?

    webpack提供了两种安全策略:

    1. hidden-source-map
    2. nosources-source-map

    hidden-source-map

    hidden-source-map意味着Webpack仍然会产出完整的map文件,但是不会在bundle文件中添加对于map文件的引用。这样当打开浏览器开发者工具时,是无法看到map文件的,自然也就无法解析。如果我们自己想要追溯源码,可使用一些第三方服务,将map文件上传到第三方服务中。目前比较流行的是Sentry(错误跟踪平台),有兴趣的可以自行搜索了解一下。

    nosources-source-map

    它对于安全性保护不如hidden-source-map,但是使用方式相对简单。当打包部署后,我们可以在浏览器开发者工具的sources选项卡中看到源码的目录结构,但是文件内容会被隐藏起来。这样,对于错误来讲,我们仍然可以在console控制台中查看源代码的错误栈,或者console日志的准确行数。对于追溯错误来说基本上够使用。

    另外的方案则是服务端配合处理,例如正常打包出source map,服务端通过服务器的nginx配置,将.map文件只对固定的白名单(如公司内网)开放,这样其余用户就无法获取到它们了,也不失为一个小妙招。

    2. 资源压缩

    资源在发布到生产环境之前,通常会进行代码压缩,也叫uglify,意思是移除多余的空格、换行、执行不到的代码块等,同时缩短变量名,在执行结果不变的前提下替换为更短的形式。

    一般工程代码在被压缩后整个体积会显著缩小。

    但同时,uglify之后的代码基本上不具有可读性,从另一个层面讲,一定程度上提高了代码的安全性

    2.1 压缩JavaScript

    压缩JS(JavaScript)的工具terser(optomization)在webpack中已集成(webpack4),并且支持ES6+的代码压缩,偏面向未来。

    示例:

    // webpack.config.js
    module.exports = {
        entry: './src/index.js',
        output: {
            filename: 'bundle.js'
        },
        // 压缩配置
        optomization: {
            minimize: true
        }
    }
    

    2.2 压缩CSS

    CSS文件的压缩前提是使用相关插件处理,先将样式提取出来,然后进行压缩。例如常使用extract-text-webpack-plugin或mini-css-extract-plugin将样式提取,然后使用optimize-css-assets-webpack-plugin来进行压缩。这个插件本质上使用的是压缩器cssnano,当然我们可以对其进行配置:

    // webpack.config.js
    const ExtractTextPlugin = require('extract-text-webpack-plugin');
    const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin')
    
    module.exports = {
        // ...
        module: {
            rules: [
                {
                    test: /\.css$/,
                    use: ExtractTextPlugin.extract({
                        fallback: 'style-loader',
                        use: 'css-loader'
                    })
                }
            ]
        },
    
        // css 压缩
        plugins: [new ExtractTextPlugin('style.css')];
        optimization: {
            minimizer: [new OptimizeCssAssetsPlugin({
                // 生效范围,只压缩匹配到的资源
                assetNameRegExp: /\.optimize\.css$/g,
                // 压缩处理器指定,默认为 cssnano
                cssProcessor: require('cssnano'),
                // 压缩处理器配置
                cssProcessorOptions: {
                    discardComments: {
                        removeAll: true
                    }
                },
                // 是否打印log
                canPrint: true
            })]
        }
    }
    

    小结

    本篇介绍了关于生产环境配置中比较重量级的两种配置:source-map和资源压缩。

    开发环境中我们关注打包速度,而在生产环境中我们关心的则是线上错误处理、输出资源的体积以及资源渲染等问题,而比较好的利用source-map和资源压缩都可以帮助我们处理处理或优化生产环境中的一些问题,因此比较重要,但同时也要注意解决所存在的安全隐患问题。

    下一篇则从缓存和bundle体积监控入手继续描述生产环境配置的其他方面优化问题。

    相关文章

      网友评论

        本文标题:webpack实战——生产环境配置【中】

        本文链接:https://www.haomeiwen.com/subject/dgfryktx.html