webpack高階教程

ITzhongzi發表於2017-04-22

1. Webpack

1.1. 網站中常見靜態資源有哪些

  1. 圖片

    • jpg,png,gif,bmp
  2. 字型

    • woff,woff2,eot,svg,ttf
  3. JS

    • js,coffee
  4. css

    • css,less,sass
  5. 模板檔案

    • .vue, .jade

1.2. 大量靜態資原始檔引發的問題

  1. 發起大量的二次請求
  2. 需要維護元件之間的依賴關係

1.3. 以上問題的解決方案

  1. 發起大量的二次請求

    • 解決方案:
    • 圖片:精靈圖,壓縮圖片體積,base64編碼(能把圖轉換為字串)
    • JS,CSS:程式碼壓縮,程式碼合併
  2. 需要維護元件之間的依賴關係:之前是程式設計師自己維護這種依賴關係的;【使用一些工具幫我們解決這種依賴關係】

1.4. webpack解決上述的問題

webpack的作用:合併檔案,壓縮檔案,處理檔案的依賴關係

1.5. 列表各行變色的案例

1.5.1. 安裝webpack

  1. 全域性安裝:執行npm i webpack -g
  2. 專案安裝:npm i webpack --save-dev
  3. --save和--save-dev的區別--save-dev的全稱:'save develop'
    • 拿jquery和webpack進行比較

1.6. 需求:

  1. 藉助於Jquery
  2. 奇數行一個顏色
  3. 偶數行一個顏色

  4. 使用npm init初始化專案,使用npm來管理專案中的包

  5. 新建HTML結構和main.js的邏輯程式碼
  6. 安裝webpackcnpm i webpack --save-dev
  7. 執行webpack src/js/main.js dist/bundle.js進行打包構建,語法是:webpack 入口檔案 輸出檔案

1.7. webpack構建的過程

  1. 判斷使用者是否傳遞了入口和出口兩個路徑,如果沒有傳遞,那麼就從專案根目錄中查詢webpack.config.js這個配置檔案
  2. 如果找到了這個配置檔案,則根據配置檔案中匯出的配置物件,來進行打包構建!
  3. 注意:在配置檔案中不能使用ES6的語法!!!

     // 1. 引入Path模組處理路徑問題
     var path = require('path');
    
     module.exports = {
         entry: path.resolve(__dirname, 'src/js/main.js'), // 配置打包的入口檔案
         output:{ // 指定輸出檔案
             path:path.resolve(__dirname, 'dist'), // 輸出檔案的路徑
             filename:'bundle.js' // 輸出檔案的名稱
         }
     }
    

1.8. 使用webpack-dev-server來實現監視程式碼實時打包,自動重新整理瀏覽器

  1. 執行cnpm i webpack-dev-server --save-dev安裝包
  2. 由於命令列不是別webpck-dev-server這個命令,所以需要在package.json中配置一下命令
  3. package.json中,script節點下的命令,可以通過npm run 命令名稱的形式去執行
  4. 注意:webpack-dev-server打包好的bundle.js檔案,並沒有存放到實際的硬碟上,而是儲存到了記憶體中!!!放到記憶體中最主要的原因是快,非常快,太TM快了!
  5. 如何從記憶體中獲取打包好的bundle.js檔案呢???
  6. 修改webpack-dev-server託管的根目錄,通過--contentBase指定託管的根目錄:
    "dev": "webpack-dev-server --contentBase src"
    
  7. 自動開啟瀏覽器和配置埠號, --open自動開啟瀏覽器, --port 4321指定埠號:
    "dev": "webpack-dev-server --contentBase src --open --port 4321"
    
  8. 在配置檔案中設定自動開啟瀏覽器:
    devServer:{ // 這裡的配置項會交給webpack-dev-server去讀取
         //--contentBase src --open --port 4321
         contentBase:path.resolve(__dirname, 'src'), // 配置啟動路徑
         open:true, // 自動開啟瀏覽器
         port:4321 // 指定埠號
     }
    

1.9. 在記憶體中生成HTML頁面

自動在記憶體中根據指定的模板,生成index頁面,同時自動注入打包好的bundle.js檔案

  1. 執行cnpm i html-webpack-plugin --save-dev
  2. 匯入模組:
    // 2. 引用自動生成HTML頁面的模組
    var htmlWebpackPlugin = require('html-webpack-plugin');
    
  3. 在配置檔案中新增plugins節點如下:
    plugins:[ // 外掛陣列
         new htmlWebpackPlugin({ // 建立一個htmlWebpackPlugin外掛
             template:path.resolve(__dirname, 'src/index.html'), // 指定模板頁面
             filename:'index.html' // 指定在記憶體中生成的頁面的名稱
         })
     ]
    

1.10. 使用Webpack打包CSS檔案

  1. 執行cnpm i style-loader css-loader --save-dev
  2. 在配置檔案中新增module節點如下:
    module:{ // 配置相關的loader模組
         rules:[ // 配置相關檔案的匹配規則
             {test:/\.css$/,  use:['style-loader', 'css-loader']}, // 處理CSS檔案的loader配置
         ]
     }
    

1.11. 使用webpack打包sass檔案

  1. 執行cnpm i sass-loader node-sass --save-dev,sass-loader依賴於node-sass
  2. 新增rules規則如下:
    { test: /\.scss$/, use: ['style-loader', 'css-loader', 'sass-loader'] }// 處理sass檔案的loader配置
    

1.12. 實現熱更新

  1. 修改package.json中的命令,新增--hot指令即可:
    "dev": "webpack-dev-server --hot"
    
  2. 第二種實現熱更新的方式:
    • 第一種方式:修改配置檔案的devServer節點:
      devServer: { // 這裡的配置項會交給webpack-dev-server去讀取
         //--contentBase src --open --port 4321
         contentBase: path.resolve(__dirname, 'src'), // 配置啟動路徑
         open: true, // 自動開啟瀏覽器
         port: 4321, // 指定埠號
         hot:true // 啟用熱更新
      },
      
    • 修改plugins節點:
      plugins: [ // 外掛陣列
         new htmlWebpackPlugin({ // 建立一個htmlWebpackPlugin外掛
             template: path.resolve(__dirname, 'src/index.html'), // 指定模板頁面
             filename: 'index.html' // 指定在記憶體中生成的頁面的名稱
         }),
         new webpack.HotModuleReplacementPlugin() // 使用webpack下面的.HotModuleReplacementPlugin()實現熱更新
      ]
      

1.13. 實現處理圖片路徑

  1. 執行cnpm i url-loader file-loader --save-dev
  2. 新增loader配置項:
    { test: /\.(jpg|png|gif|bmp|jpeg)$/, use: 'url-loader' } // 處理URL路徑的loader
    
  3. url-loader預設能幫我們把圖片轉為base64編碼;
  4. 預設URL中的圖片路徑是經過雜湊求值的,目的是為了防止兩張一模一樣的圖片出現;
  5. limit引數的作用:給定一個圖片的大小,當圖片超過給定值的時候:就證明你是一張大圖片,不用進行base64編碼;否則:是小圖片,需要進行base64編碼;
  6. 計算機中儲存的單位:Bit,Byte,KB,MB,GB,TB
  7. limit=1000中單位是Byte,只要當圖片小於給定值的時候,才會進行base64的編碼!

1.14. ES6中的class關鍵字

  1. 靜態屬性和例項屬性的區別:
    • 靜態屬性:直接通過類名就可以訪問到,不需要建立類的例項;
    • 例項屬性:必須先通過new關鍵字,建立一個類的例項,然後,在這個例項上通過點號訪問的屬性,叫做例項屬性;
    • 由於webpack不識別靜態屬性static這個關鍵字,所以,需要藉助於babel-loader來處理這個高階ES6語法!

1.15. 在webpack中配置babel-loader

  1. 執行npm i cnpm -g
  2. 執行cnpm i babel-core babel-loader babel-plugin-transform-runtime --save-dev
  3. 執行cnpm i babel-preset-es2015 babel-preset-stage-0 --save-dev
  4. 新增相關loader模組:
    {test:/\.js$/, use:'babel-loader', exclude:/node_modules/} // 最重要的一點:要把node_modules資料夾,新增到排除項,通過exclude排除這個資料夾【注意:一定要排除否則會報錯!!!】
    
  5. 在專案根目錄中新建.babelrc配置檔案,將來babel-loader執行的時候,會檢查這個配置檔案,並讀取相關的語法和外掛配置:
    {
     "presets":["es2015", "stage-0"],
     "plugins":["transform-runtime"]
    }
    

1.16. Webpack釋出策略

  1. 開發期間的配置:實時重新整理瀏覽器,實時編譯,熱更新,index.html,bundle.js;
  2. 在開發期間:測試檔案、測試資料、測試相關的工具(好處:方便快速開發除錯)
  3. 部署期間:剔除(測試檔案、測試資料、測試相關的工具)這些檔案,目的:減少部署檔案的體積;方便使用者安裝;
  4. 在部署時候,我們也需要一個webpack的配置檔案,只是這個配置檔案中,刪除了開發時候的一些工具;
  5. 在專案中新建webpack.publish.config.js
     // 刪除devServer選項:
     devServer: { // 這裡的配置項會交給webpack-dev-server去讀取
         //--contentBase src --open --port 4321
         contentBase: path.resolve(__dirname, 'src'), // 配置啟動路徑
         open: true, // 自動開啟瀏覽器
         port: 4321, // 指定埠號
         hot: true // 啟用熱更新
     },
    
     // 刪除熱更新
         new webpack.HotModuleReplacementPlugin() // 使用webpack下面的.HotModuleReplacementPlugin()實現熱更新
    
     // 改造URL-loader
     { test: /\.(jpg|png|gif|bmp|jpeg)$/, use: 'url-loader?limit=43959&name=images/imgs-[hash:7].[ext]' }, // 處理URL路徑的loader
    

1.17. 每次重新發布的時候,自動刪除dist目錄

  1. 執行cnpm i clean-webpack-plugin
  2. 在部署的配置檔案中匯入這個外掛:
    var cleanWebpackPlugin = require('clean-webpack-plugin');
    
  3. 在plugins節點下,建立這個麼一個外掛,把需要刪除的目錄通過陣列傳遞進去:
    new cleanWebpackPlugin(['dist']) // 建立一個刪除資料夾的外掛,把dist目錄傳遞進去
    

1.18. 分離第三方包

目的:將公共的第三方包,抽離為一個單獨的包檔案,這樣防止重複打包!

  1. 改造entry:
    entry: {
         app:path.resolve(__dirname, 'src/js/main.js'), // 自己的程式碼入口檔案
         vendors:['jquery'] // 第三方包的入口
     }, // 配置打包的入口檔案
    
  2. 改造plugins:
    new webpack.optimize.CommonsChunkPlugin({
             name:'vendors', // 指定抽取公共模組的名稱
             filename:'vendors.js' // 指定抽取出來的檔案真實名稱
         })
    

1.19. 壓縮JS程式碼

在Plugins下面新增:

new webpack.optimize.UglifyJsPlugin({ // 優化壓縮JS
    compress:{
        warnings:false // 移除警告
    }
}),
new webpack.DefinePlugin({ // 設定為產品上線環境,進一步壓縮JS程式碼
    'process.env':{
        'NODE_ENV':JSON.stringify('production')
    }
})

1.20. 抽取CSS檔案到單獨的樣式表

  1. 執行cnpm install --save-dev extract-text-webpack-plugin
  2. 引入外掛:
    var ExtractTextPlugin = require("extract-text-webpack-plugin");
    
  3. 修改sass和css的loader如下:
    {
         test: /\.css$/, use: ExtractTextPlugin.extract({// 使用外掛來處理CSS樣式
             fallback: "style-loader",
             use: "css-loader"
         })
     }, // 處理CSS檔案的loader配置
     {
         test: /\.scss$/, use: ExtractTextPlugin.extract({
             fallback: 'style-loader',
             use: ['css-loader', 'sass-loader']
         })
     },// 處理sass檔案的loader配置
    
  4. 在plugins下面新增新外掛:
    new ExtractTextPlugin("styles.css") // 抽離CSS樣式名稱
    

1.21. 壓縮抽取出來的CSS 樣式表

  1. 執行cnpm i optimize-css-assets-webpack-plugin --save-dev安裝外掛
  2. 匯入外掛:
    var OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
    
  3. 在plugins節點下new上面匯入的外掛即可:
    new OptimizeCssAssetsPlugin() // 建立一個壓縮CSS檔案的外掛
    

1.22. 壓縮HTML頁面

  1. 修改plugins節點下面的htmlWebpackPlugin這個外掛,新增minify屬性;
    new htmlWebpackPlugin({ // 建立一個htmlWebpackPlugin外掛
         template: path.resolve(__dirname, 'src/index.html'), // 指定模板頁面
         filename: 'index.html', // 指定在記憶體中生成的頁面的名稱
         minify:{ // 壓縮優化HTML頁面
             collapseWhitespace:true, // 合併空白字元
             removeComments:true, // 移除註釋
             removeAttributeQuotes:true // 移除屬性上的引號
         }
     })
    
  2. 詳細的配置可以參考html-minifier https://github.com/kangax/html-minifier#options-quick-reference

相關文章