webpack實戰——生產環境配置【中】

前言

上一篇中,描述了一些關於生產環境的配置:環境變量的使用、配置文件描述、開啓生產模式、環境變量自定義配置等,從這幾個方面入手都可以對生產環境產生一些有利影響。

那麼本篇,從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體積監控入手繼續描述生產環境配置的其他方面優化問題。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章