webpack基礎知識

wyao發表於2019-07-25

一、基礎

1 安裝

npm i -g webpack webpack-cli

// 推薦安裝至本地
npm i -D webpack webpack-cli

2 webpck基礎使用

2.1 webpack-cli

Npm 5.2以上的版本中提供了一個npx命令

npx想要解決的主要問題、就是呼叫專案內部安裝的模組、即就是在node_modules下的.bin目錄中找到對應的命令執行

使用webpack命令: npx webpack

Webpack4.0之後可以實現0配置打包構建、0配置的特點就是限制較多、無法自定義很多配置

開發過程中還是使用webpack配置進行打包構建

2.2 webpack配置

Webpack 四大核心概念

  • 入口entry — 程式的入口js
  • 輸出 output — 打包後存放的位置
  • 載入器loader — 用於對模組的原始碼進行轉換
  • 外掛plugins — 解決loader無法解決的問題

基本配置

  1. 配置 webpack.comfig.js
  2. 執行 npx webpack
// 執行預設webpack.config.js檔案 
npx webpack
npx webpack webpack.config.js

// 執行自定義配置檔案
npx webpack --config webpack.custom.config.js

//package.json 配置
"dev": "webpack --config webpack.custom.config.js",
"dev1": "npx webpack --config webpack.custom.config.js", // npx 可省略、會自動在node_modules裡面找
"dev2": "webpack"
const path = require('path')

module.exports = {
  entry: './src/index.js',
  output: {
    path: path.join(__dirname, 'dist'),
    filename:'bundle.js'
  },
  mode: 'development'
}

2.3 自動編譯工具配置

每次要編譯程式碼時,需要執行npm run dev比較煩,webpack提供了幾個選項、可以自動編譯

  1. webpack watch mode
  2. webpack-dev-server
  3. webpack-dev-middleware

多數場景中、推薦使用webpack-dev-server

2.3.1 watch

webpack指令後面加上--watch引數即可

主要的作用就是監視本地專案檔案的變化、發現有修改的程式碼就會自動編譯打包、生成輸出檔案

  • 通過cli的方式設定watch引數
  1. 配置package.json

    "watch": "webpack --watch"
  2. 執行 npm run watch

  • 通過配置檔案對watch的引數進行修改
const path = require('path')

module.exports = {
  mode: 'development',
  entry: './src/index.js',
  output: {
    path: path.join(__dirname, 'dist'),
    filename:'bundle.js'
  },
  // 開啟監視模式、此時執行webpack指令進行打包會監視檔案變化自動打包
  watch: true
}

2.3.2webpack-dev-server (重點)

  • 簡單配置
  1. 安裝devServer

    安裝devServer需要依賴webpack、必須在專案依賴中安裝webpack

    npm i -D webpack-dev-server

  2. index.html中

    <script src='/bundle.js'></script>
  3. 執行

    npx webpack-dev-server
  4. 執行

    npx webpack-dev-server --hot --open --port 9527
  5. 配置package.json

    "dev": "webpack-dev-server  --contentBase src --compress --hot --open --port 9527"
    
    // --contentBase src 是以src為根目錄, 否則以專案為根目錄
    // --open 自動開啟
    // --port 埠號
    // --hot 熱模組更新
    // --compress 利用express開啟gzip壓縮
  6. 執行

    npm run dev

devServer 會在記憶體中生成一個大包好的bundle.js, 專供開發時使用,打包效率高,修改程式碼後會自動打包重新打包以及重新整理瀏覽器

  • 修改webpack.config.js
const path = require('path')

module.exports = {
  mode: 'development',
  entry: './src/index.js',
  output: {
    path: path.join(__dirname, 'dist'),
    filename:'bundle.js'
  },
  // 將cli中的引數 在配置檔案中進行配置
  devServer:{
    hot:true,
    open: true,
    port:9527,
    compress: true,
    contentBase:'./src'
  }
}

2.3.3 html外掛

  1. 安裝 html-webpack-plugin 外掛

    npm i -D html-webpack-plugin
  2. webpack.config.js 中 plugins 節點下配置

    const HtmlWebpackPlugin = require('html-webpack-plugin')
    
    plugins:[
     new HtmlWebpackplugin({
         filename: 'index.html', // 生產的檔名稱
         template: './src/index.html' // 將此目錄下的檔案作為模板生成一個新的html、放置在根目錄的記憶體中
     })
    ]
    1. devServer時、根據模板在express專案根目錄下生成html檔案、類似於devServer生成記憶體中的bundle.js
    2. devServer時、自動引入 bundle.js
    3. 打包時會自動生成index.html

2.3.4 webpack-dev-middleware

webpack-dev-middleware 是一個容器(wrapper)、它可以把webpack處理後的檔案傳遞給一個伺服器(server)、webpack-dev-server 在內部使用了它、同時、它可以作為一個單獨的包來使用、以便進行更多自定義設定來實現更多的需求

  1. 安裝express 和 webpack-dev-middleware

    npm i -D express webpack-dev-middleware
  2. 新建 server.js

    const express = require('express')
    const webpack = require('webpack')
    const webpackDevMiddleware = require('webpack-dev-middleware')
    const config = require('./webpack.config')
    
    const app = express()
    const compiler = webpack(config)
    
    app.use(webpackDevMiddleware(compiler, {
      publicPath:'/'
    }))
    
    app.listen(3333, function () {
      console.log('port:3333');
    })

    如果要使用middleware、必須使用html-webpack-plugin外掛、否則html檔案無法正確的輸出到express伺服器的根目錄

2.3.5 總結

只有在開發時才需要使用自動編譯工具

專案上線時都會直接使用webpack進行打包構建、不需要使用這些自動編譯工具

自動編譯工具只是為了提高開發體驗

2.4處理CSS

  1. 安裝 css-loader style-loader

    npm i -D css-loader style-loader
  2. 配置web pack

    module:{
     rules:[
         // 配置的是用來解析.css檔案的loader,css-loader、style-loader
         // css-loader -- 解析css檔案
         // style-loader -- 將解析出來的結果 放到html中 使其生效
         {
             test:/\.css$/,
             use:['style-loader', 'css-loader'] // webpack底層呼叫這些loader的順序是從右向左
         }
     ]
    }

2.5 處理less和scss

  1. 安裝

    npm i -D less less-loader sass-loader node-sass
  2. 配置less

    {
     test:/\.less$/,
     use:['style-loader', 'css-loader', 'less-loader']
    }
  3. 配置sass

    {
     test:/\.scss$/,
     use:['style-loader', 'css-loader', 'sass-loader']
    }

2.6處理圖片和字型

  1. 下載、url-loader 封裝了 file-loader

    npm i -D file-loader url-loader
  2. 配置

    1. 配置 filte-loader
    { // 處理圖片
      test: /\.(png|jpg|gif)$/,
      use: 'file-loader'
    },
    { // 處理字型圖示檔案
      test: /\.(woff|woff2|eot|svg|ttf)$/,
      use: 'file-loader'
    },
    1. 配置url-loader
    {
     test:/\.(png|jpg|gif)$/,
     use:{
         loader: 'url-loader',
         options: {
             // limit 表示若圖片的大於5KB、就以路徑的形式展示、小於的話就用base64格式展示
             limit: 5 * 1024,
          outputPath:'images', // 圖片生成的資料夾名稱
          name:'[name]-[hash:6].[ext]' // 生成的圖片名稱
         }
     }
     //use 也可以寫成陣列
     use:[{
        loader:'url-loader',
        options:{
         limit: 12 * 1024
        }
      }]
    }

2.7 babel

  1. 安裝

    npm i -D babel-loader @babel/core @babel/preset-env
  2. 如果需要支援更高階別的es6語法、可以繼續安裝外掛、在官網找對應的外掛安裝

    npm i -D @babel/plugin-proposal-class-properties 
  3. 配置

    {
     test: /\.js$/,
     use: {
         loader: 'babel-loader',
         options: {
             presets: ['@babel/env'],
             plugins: ['@babel/plugin-proposal-class-properties']
         }
     },
     exclude: /node_modules/,
     include: path.resolve(__dirname, '../src')
    }

官方更加建議使用 .babelrc 配置

{
 "presets": ["@babel/env"],
 "plugins": ["@babel/plugin-proposal-class-properties"]
}

3.1 如果需要使用 genetator,無法直接使用 babel 進行轉換,因為會將 generator 轉換為一個 regeneratorRuntime, 然後使用 mark 和 wrap 來實現 generator

  • 安裝外掛

    npm i -D @babel/plugin-transform-runtime 
    npm i -S @babel/runtime
  • 配置中、修改 plugins

    
    plugins: [
     '@babel/plugin-proposal-class-properties',
     '@babel/plugin-transform-runtime'
    ]

3.2 如果需要使用 ES6/7 中物件原型提供的新方法,babel 預設情況無法轉換,即使用了 plugin-transform-runtime 的外掛也不支援轉換原型上的方法,需要使用 polyfill

  • 安裝

    npm i -S @babel/polyfill
  • 在需要使用該模組的地方直接引入

    import '@babel/polyfill'

2.8 外掛

2.8.1 clean-webpack-plugin

該外掛可以用於自動清除dist目錄後重新生成,在 npm run build 的時候非常有用

  1. 安裝外掛

    npm i -D clean-webpack-plugin
  2. 引入外掛

    const {CleanWebpackPlugin} = require('clean-webpack-plugin')
  3. 配置外掛

    plugins:[
      new HtmlWebpackPlugin({
        filename: 'index.html',
        template: './src/index.html'
      }),
      new CleanWebpackPlugin()
    ],

2.8.2 copy-webpack-plugin

  1. 安裝

    npm i -D copy-webpack-plugin
  2. 引入外掛

    const CopyPlugin = require('copy-webpack-plugin');
  3. 配置外掛

    from:源、從哪裡拷貝,可以是絕對路徑或者絕對路徑,推薦絕對路徑

    to:目標、拷貝到哪裡去,相對於output的路徑,同樣可以是相對路徑或者絕對路徑,更推薦相對路徑、直接相對於dist目錄即可

    plugins:[
      new HtmlWebpackPlugin({
        filename: 'index.html',
        template: './src/index.html'
      }),
      new CleanWebpackPlugin(),
      new CopyPlugin([
        { 
          from: path.join(__dirname, 'static'),
          to: 'static'
        }
      ])
    ],

2.8.3 BannerPlugin

是一個webpack內建外掛、用於給打包的js檔案加上版權註釋資訊

  1. 引入webpack外掛

    const webpack = require('webpack')
  2. 配置

    plugins:[
      new HtmlWebpackPlugin({
        filename: 'index.html',
        template: './src/index.html'
      }),
      new CleanWebpackPlugin(),
      new CopyPlugin([
        { 
          from: path.join(__dirname, 'static'),
          to: 'static'
        }
      ]),
      new webpack.BannerPlugin('王耀的版權資訊')
    ],