1. 程式人生 > 實用技巧 >打包工具:Webpack

打包工具:Webpack

參考:

  官網:https://webpack.js.org/guides/getting-started/

  原文:https://segmentfault.com/a/1190000021395777

  本文demo(webpack5):https://gitee.com/open_-_code/webpack_demo.git

webpack demo

  1 初始化專案

    初始化npm

npm init -y

    安裝依賴

npm install webpack webpack-cli --save-dev

    建立src檔案,src下建立index.js

    

// index.js
console.log('hello webpack')

    配置package.json

  "scripts": {
    "build": "webpack"
  },

    執行npm run build

    此時如果生成了一個dist資料夾,並且內部含有main.js說明已經打包成功了

  2 配置自己的配置

    新建一個webpack.config.js

    

// webpack.config.js
const path = require('path');

module.exports = {
    mode:'development', // 開發模式
    entry: './src/index.js',  //
入口檔案 output: { filename: 'main.js', // 打包後的檔名稱 path: path.resolve(__dirname, 'dist'), // 打包後的目錄 }, };

    更改package.json

    "scripts": {
      "build": "webpack --config webpack.config.js"
    },

    執行npm run build,其中dist資料夾中的main.js就是我們需要在瀏覽器中實際執行的檔案

  3 配置html模板

    為了快取,日常開發時,webpack.config.js往往會這樣配置

// webpack.config.js
const path = require('path');

module.exports = {
    mode:'development', // 開發模式
    entry: './src/index.js',  // 入口檔案
    output: {
        filename: '[name].[hash:8].js',    // 打包後的檔名稱
        path: path.resolve(__dirname, 'dist'),  // 打包後的目錄
    },
};

    你會發現打包好的js檔案的名稱每次都不一樣

    

    webpack打包出來的js檔案我們需要引入到html中,但是每次我們都手動修改js檔名顯得很麻煩,因此我們需要一個外掛來幫我們完成這件事情

npm i -D html-webpack-plugin

    新建資料夾public,裡面新建一個index.html

    引入外掛html-webpack-plugin,修改webpack.config.js

// webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
    mode:'development', // 開發模式
    entry: './src/index.js',  // 入口檔案
    output: {
        filename: '[name].[hash:8].js',    // 打包後的檔名稱
        path: path.resolve(__dirname, 'dist'),  // 打包後的目錄
    },
    plugins:[
        new HtmlWebpackPlugin({
          template:path.resolve(__dirname,'./public/index.html')
        })
    ]
};

    執行打包命令,打包生成的js檔案已經被自動引入html檔案中

    

    多檔案入口開發,修改webpack.config.js

// webpack.config.js    
plugins:[
        new HtmlWebpackPlugin({
          template:path.resolve(__dirname,'./public/index.html'),
          filename:'index.html',
          chunks:['main'] // 與入口檔案對應的模組名
        }),
        new HtmlWebpackPlugin({
            template:path.resolve(__dirname,'./public/header.html'),
            filename:'header.html',
            chunks:['header'] // 與入口檔案對應的模組名
        }),
]

    執行打包命令生成目錄

    

    每次執行npm run build 會發現dist資料夾裡會殘留上次打包的檔案,這裡我們推薦一個plugin來幫我們在打包輸出前清空資料夾clean-webpack-plugin

npm i -D clean-webpack-plugin
// webpack.config.js
const {CleanWebpackPlugin} = require('clean-webpack-plugin')
module.exports = {
    // ...省略其他配置
    plugins:[new CleanWebpackPlugin()]
}

  4 引入css

    我們的入口檔案是js,所以我們在入口js中引入我們的css檔案

// index.js

import '/src/assets/index.css'
import '/src/assets/index.less'
console.log('hello webpack')

    同時我們也需要一些loader來解析我們的css檔案

npm i -D style-loader css-loader

    如果我們使用less來構建樣式,則需要多安裝兩個

npm i -D less less-loader
// webpack.config.js

module.exports = {
    // ...省略其他配置
    module:{
      rules:[
        {
          test:/\.css$/,
          use:['style-loader','css-loader'] // 從右向左解析原則
        },
        {
          test:/\.less$/,
          use:['style-loader','css-loader','less-loader'] // 從右向左解析原則
        }
      ]
    }
}

    執行打包命令,瀏覽器開啟dist下的index.html

    

  4.1 為css新增瀏覽器字首

npm i -D postcss-loader autoprefixer
// webpack.config.js

module.exports = {
    // ...省略其他配置
    module:{
      rules:[
          {
            test:/\.less$/,
            use:['style-loader','css-loader','postcss-loader','less-loader'] // 從右向左解析原則
          }
      ]
    }
}

    根目錄下建立postcss.config.js

// postcss.config.js

module.exports = () => {
    return {
        plugins: {
            'autoprefixer': {
                overrideBrowserslist: ['Android >= 4.0', 'iOS >= 7']
            },
        }
    }
}

    這時候我們發現css通過style標籤的方式新增到了html檔案中,但是如果樣式檔案很多,全部新增到html中,難免顯得混亂。這時候我們想用把css拆分出來用外鏈的形式引入css檔案怎麼做呢?這時候我們就需要藉助外掛來幫助我們

  4.2 拆分css

    webpack 4.0以前,我們通過extract-text-webpack-plugin外掛,把css樣式從js檔案中提取到單獨的css檔案中。webpack4.0以後,官方推薦使用mini-css-extract-plugin外掛來打包css檔案

npm i -D mini-css-extract-plugin

// webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
  //...省略其他配置
  module: {
    rules: [
          {
            test:/\.css$/,
            use:[MiniCssExtractPlugin.loader,'css-loader','postcss-loader'] // 從右向左解析原則
          },
          {
            test:/\.less$/,
            use:[MiniCssExtractPlugin.loader,'css-loader','less-loader','postcss-loader'] // 從右向左解析原則
          },
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({
        filename: "[name].[hash].css",
        chunkFilename: "[id].css",
    })
  ]
}

  5 打包圖片、字型、媒體等檔案

      file-loader就是將檔案在進行一些處理後(主要是處理檔名和路徑、解析檔案url),並將檔案移動到輸出的目錄中

      url-loader一般與file-loader搭配使用,功能與 file-loader 類似,如果檔案小於限制的大小。則會返回 base64 編碼,否則使用 file-loader 將檔案移動到輸出的目錄中

// webpack.config.js
module.exports = {
  // 省略其它配置 ...
  module: {
    rules: [
      // ...
      {
        test: /\.(jpe?g|png|gif)$/i, //圖片檔案
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 10240,
              fallback: {
                loader: 'file-loader',
                options: {
                    name: 'img/[name].[hash:8].[ext]'
                }
              }
            }
          }
        ]
      },
      {
        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, //媒體檔案
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 10240,
              fallback: {
                loader: 'file-loader',
                options: {
                  name: 'media/[name].[hash:8].[ext]'
                }
              }
            }
          }
        ]
      },
      {
        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/i, // 字型
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 10240,
              fallback: {
                loader: 'file-loader',
                options: {
                  name: 'fonts/[name].[hash:8].[ext]'
                }
              }
            }
          }
        ]
      },
    ]
  }
}

  

  6 用babel轉義js檔案

npm install -D babel-loader @babel/core @babel/preset-env
    • 注意

    babel-loaderbabel-core的版本對應關係

      1. babel-loader8.x 對應babel-core7.x
      2. babel-loader7.x 對應babel-core6.x

    

// webpack.config.js
module.exports = {
    // 省略其它配置 ...
    module:{
        rules:[
          {
            test:/\.js$/,
            use:{
              loader:'babel-loader',
              options:{
                presets:['@babel/preset-env']
              }
            },
            exclude:/node_modules/
          },
       ]
    }
}

    上面的babel-loader只會將 ES6/7/8語法轉換為ES5語法,但是對新api並不會轉換 例如(promise、Generator、Set、Maps、Proxy等)

cnpm i @babel/polyfill -D
// webpack.config.js
const path = require('path')
module.exports = {
    entry: ["@babel/polyfill",path.resolve(__dirname,'./src/index.js')],    // 入口檔案
}

    over!!