2020年,《深刻淺出Webpack》(吳浩麟2018/01)學習總結

前言

2020年1月18號,還有一週就是農曆2020年的春節了,我提早請了6天的假,回家過年。此時公司的項目仍是如火如茶的開展,一如既往的趕工。css

原本打算年前辭去工做,回家過個長春節,來年金三銀四江湖再會。(畢竟,這是我二十多年來,第一次回老家過年)html

待遇通常,配的也是租來的黑瞎眼的古董thinkPad T430筆記本,每天無條件加班9->0點。要是我辭,試用期內,不辭,過完年就過試用期了,考慮到新項目尚未作完(期實也就是作了一個月,可是已完成7成了),負責任的我猶豫了好久,沒有提交那份書。前端

拿了在這裏上班的第一個月工資,以及賣掉了本身的遊戲本,換了一個二手的macbook pro。vue

剛入行前端的頭一年,我知道,我要的是知識,我要的不是沒日沒夜的加班,還有不停的百度,不停的試完一個博客的案例發現不合適又找下一個。node

應了當前項目兩個開發環境,三個打包路徑改來改去的痛點,我決定在這個春節,怎麼也要抽點時間出來看完這本《深刻淺出Webpack》。webpack

看的是電子書,2018年1月發售的,在京東上找,這本書還在買。看了京東對本書的簡介好像並無更新。書中用的webpack 是@2版並穿插@3版本。據說webpack 4有了相對大的更新,目前好像更新到了5,別說老油條,我一個新人,都以爲前端學起來費勁。web

截屏2020-02-03下午10.09.27.png

對於書上的安裝方法來裝各個工具是版本是不對的。可是能不能用,出現的坑,我都在下文的總結中列出來吧。vue-cli

本次學習沒有過深研究webpack,參照了vue-cli2.9版本搭建的webpack模版,以及webpack 4.4的官方中文文檔(不知道怎麼能看到舊文檔),對於要在vue項目中用到的一些配置做了學習。npm

後期跟據須要會不斷的完善這份總結。json

有不少過來人都說前端更新快,看書學習不是最佳方法(考慮到書的價格不低),可是我仍是比較喜歡看書,本身也買了不少書,這本是到目前爲止看的惟一一本電子書。這本書到底值不值看?

前半部分對api的介紹沒有webpack官方文檔好理解,可是後半段對webpack的配置優化總結及一些按例仍是很值得新手去看

DevServer

文中沒有很明確說到如何啓動build和運行webpack中的命令,

期實,運行webpack就是在終端中(進入當前文件夾)輸入webpack,回車後項目就打包放在dist文件夾了,可是,這時打包的結果是一個js文件,入口index.html文件仍是在dist同級目錄下的那個index.html。

當你的webpack沒有全局安裝時,不能直接在終端中輸入webpack,而是要輸入webpack所在的文件,在node_modules/.bin/webpack。直接輸入

node_modules/.bin/webpack

回車。

運行devServer時也是在這個目錄下

node_modules/.bin/webpack-dev-server

要看到熱更新,還要改一下入口文件index.html中的bundle.js的路徑,由於devserver不會理會webpack.config.js裏的output.path屬性。

<script src="./dist/bundle.js" ></script>
<!-- 改成下面的--!>
<script src="bundle.js"></script>

固然這些命令是能夠寫在package.json文件裏的script下,而後經過npm run 去運行的

1EkUFs.md.png

Entry

1. context(webpack默認的打包相對路徑)

更改:在webpack的配置文件中:

const    path = require('path');
{
    context: path.resolve(__dirname,'app'),//或者 ./ ../ 等
}

2. 入口文件

entry: {
    app: './src/main.js',//能夠配置多個入口,或動態入口
}

3. output

output: {
    filename: '[name].js',//[name]是node內置的name變量
    path: path.resolve(__dirname, '../dist'),//必須是絕對路徑,經過之path能夠找出絕對路徑。
    publicPath: '',
}

說明:

filename 輸出文件的名稱

path 輸出文件存放在本地的目錄

publicPath 異步加載的地址,(發佈到線上資源的URL前綴)

4. resolve

配置模塊如何解析,

alias

改import後面的引用路徑,從而達到簡寫

resolve: {
    alias: {
        "@": resolve('src'),//resolve方法是找到src是絕對地址
        "vue$": './src/vue/'
    }
}
//當引用
import Comp from 'vue$/vue';
import Button from '@/components/button';
//實際會被改爲
import Comp from './src/vue/vue';
import Button from './src/components/button';

extensions

使import 的引用路徑不用寫相應的後綴名,

resolve: {
    extensions: ['.js','.json'],//默認值
    //extensions: ['.js','.vue','.json'],vue項目能夠加入'.vue'
}

5. devServer

用於描述web pack-dev-server的行爲選項

hot

模塊熱替換採用不刷新整個頁面,而是熱替換有變動的模塊來更新瀏覽器視圖,默認是刷新整個頁面

devServer: {
    hot: true,
}

historyApiFallback

用於方便開發使用了HTML5 History API的單頁面應用

當設爲:

devServer: {
    historyApiFallback: true,
}

任意的 404 響應均可能須要被替代爲 index.html,但只能應用於只有一個html文件的應用。

若是要devServer能跟據不一樣的頁面請求後回不周的html文件,配置:

historyApiFallback: {
  rewrites: [
    // /user開頭的都返回user.html
    { from: /^\/user/, to: '/user.html'},
    { from: /^\/game/, to: './game.html'},
    //其餘的返回index.html
    { from: /./, to: '/index.html'}
  ]
}

compress

host

port

open

boolean,在devServer啓動且第一次構建完成時,自動打開系統默認瀏覽器

proxy

使用了http-proxy-middleware包,用於代理url。

直接代理:

devServer: {
    proxy: {
        "/api": "http://localhost:3000",
    }
}

當請求/api/index時會被代理到 'http://localhost:3000/api/index'

若是你不想始終傳遞 /api ,則須要重寫路徑:

proxy: {
    "/api": {
        target: "http://localhost:3000",
        pathRewrite: {
            "^/api": "",
        }
    }
}

若是是https請求加入source: false,

proxy: {
    source: false,//source直譯:安全的
}

解決跨域:changeOrigin

proxy: {
    changeOrigin: true,
}

本地就會虛擬一個服務器接收你的請求並代你發送該請求

quiet

boolean

啓用 quiet 後,除了初始啓動信息以外的任何內容都不會被打印到控制檯。這也意味着來自 webpack 的錯誤或警告在控制檯不可見。

webpack的其餘零散配置

1. target

構建針對不一樣運行環境的代碼

2. devtool

配置如何生成source Map,以方便調試

string boolean

默認: false

不一樣的值會明顯影響到構建(build)和從新構建(rebuild)的速度。

vue-cli2中應在development開發環境的devtool爲:cheap-module-eval-source-map

對於適合開發環境的值,webpack文檔中有以下說明:

eval - 每一個模塊都使用 eval() 執行,而且都有 //@ sourceURL。此選項會很是快地構建。主要缺點是,因爲會映射到轉換後的代碼,而不是映射到原始代碼(沒有從 loader 中獲取 source map),因此不能正確的顯示行數。

eval-source-map - 每一個模塊使用 eval() 執行,而且 source map 轉換爲 DataUrl 後添加到 eval() 中。初始化 source map 時比較慢,可是會在從新構建時提供比較快的速度,而且生成實際的文件。行數可以正確映射,由於會映射到原始代碼中。它會生成用於開發環境的最佳品質的 source map。

cheap-eval-source-map - 相似 eval-source-map,每一個模塊使用 eval() 執行。這是 "cheap(低開銷)" 的 source map,由於它沒有生成列映射(column mapping),只是映射行數。它會忽略源自 loader 的 source map,而且僅顯示轉譯後的代碼,就像 eval devtool。

cheap-module-eval-source-map - 相似 cheap-eval-source-map,而且,在這種狀況下,源自 loader 的 source map 會獲得更好的處理結果。然而,loader source map 會被簡化爲每行一個映射(mapping)。

Vue-cli2在build生產環境中的devtool爲: #source-map

不知道爲何加了一個'#'

對於適合生產環境的值,webpack文檔中有以下說明:

(none)(省略 devtool 選項) - 不生成 source map。這是一個不錯的選擇。

source-map - 整個 source map 做爲一個單獨的文件生成。它爲 bundle 添加了一個引用註釋,以便開發工具知道在哪裏能夠找到它。

你應該將你的服務器配置爲,不容許普通用戶訪問 source map 文件!

hidden-source-map - 與 source-map 相同,但不會爲 bundle 添加引用註釋。若是你只想 source map 映射那些源自錯誤報告的錯誤堆棧跟蹤信息,但不想爲瀏覽器開發工具暴露你的 source map,這個選項會頗有用。

你不該將 source map 文件部署到 web 服務器。而是隻將其用於錯誤報告工具。

nosources-source-map - 建立的 source map 不包含 sourcesContent(源代碼內容)。它能夠用來映射客戶端上的堆棧跟蹤,而無須暴露全部的源代碼。你能夠將 source map 文件部署到 web 服務器。

這仍然會暴露反編譯後的文件名和結構,但它不會暴露原始代碼。

在使用 uglifyjs-webpack-plugin 時,你必須提供 sourceMap:true 選項來啓用 source map 支持。

其中,devtool有六個值,這六個值能夠隨意組合:

  1. eval: 用eval語句包裹須要安裝的模塊。
  2. source-map: 生成獨立的source map文件
  3. hidden: 不在js文件中指出source map文件所在,這樣瀏覽器就不會自動加載source map.
  4. inline: 將生成的source map轉換成base64格式內嵌在js文件中。
  5. cheap: 在生成的source map中不會包含列信息,這樣計算量更小,輸出的source map文件更小;同時 loader輸出的 source map不會被採用。
  6. module: 來自loader的 source map被簡單處理成每一行一個模塊。

3. watch和watchOptions

watch

webpack的監聽模式,它支持監聽文件更新,在文件發生變化時從新編譯。

默認爲false

在webpack-dev-server 和 web pack-dev-middleware中是默認開啓的。

watchOption是相應的配置

npm script

也就是webpack的命令,寫在package.json的script字段裏

代碼檢查

經常使用工具: ESlint、TSlint、stylelint

價紹了ESlint的一些設定,TSlint用於TypeScript,stylelint用於css

file-loader與url-loader

  1. File-loader

    改變打包後的文件名,以方便尋找路徑,用hash命名。

  2. Url-loader

    將小文件的資源改成base64格式以嵌入代碼中。

    好處:http/1協議中,每加載一次資源都要創建一次http請求,將小圖片注入代碼中能夠減小這一次請求

    很差處: 會導至js/css代碼體積變大,文件過大將使網頁加載緩慢。

    module.export = {
        module: {
            rules: [
                {
                    test: /\.png$/,
                    use: [
                        {
                            loader: 'url-loader',
                            options: {
                                //30KB如下的文件採用url-loader,
                                limit: 1024*03,
                                //不然用file-loader,
                                fallback: 'file-loader',
                            }
                        }
                    ]
                }
            ]
        }
    }

webpack優化

踩坑1: 更改paralleUglifyPlugin並無加快打包的速度

個人項目是用vue-cli2拉的默認環境,開發了一段時間,也加入了好多第三方包。平時的打包大概是50秒,改爲paralleUglifyPlugin後,時間爲48.5秒。

其中,配置時也有不少報錯:正確的配置:

new ParallelUglifyJsPlugin({
    //uglifyJs要改成uglifyES(求上傳服務器驗證)
  uglifyES: {
    output: {
      beautify: false,
      comments: false,
      }
  },
  compress: {
      warnings: false,
    drop_console: true,
    collapse_vars: true,
    reduce_vars: true,
  },
  sourceMap: config.build.productionSourceMap,//false
  parallel: true,
}),

區分環境

書中介紹的方法是設置process.env.NODE_ENV

const DefinePlugin = require('webpack/lib/DefinePlugin');

module.export = {
    plugins: [
        new DefinePlugin({
            'process.env': {
                NODE_ENV: JSON.stringify('production')
            }
        })
    ]
}
在定義環境時用JSON.stringify的緣由是,環境烴量的值須要是一個由雙引號包裹的字符串,而JSON.stringify('production')的值正好等於'"production"'
相關文章
相關標籤/搜索