Webpack教程~保姆級入門篇

基礎概念

官網安裝方式css

經過官網的指引安裝好webpack,在項目根目錄添加 webpack.config.js 的文件. webpack.config.js 遵循的是 commonJS 規範,依次文件採用 module.exports={[key]:[value]} 的方式,來暴露具體的配置。html

一個基本的webpack配置以下node

module.exports = {
  entry: "[xxx].js",
  output: {
    filename: 'xxxx.js',
    path: resolve(__dirname, 'xxx')
  },
  module: {
    rules: [
      {[key]:[value]}
    ]
  },
  plugins: [
    new PluginsName()
  ],
  mode: 'production | development'
}
複製代碼

官網基礎概念webpack

Entry

指定webpack,打包的起始文件,根據此文件分析構建依賴關係圖。git

入口文件,可配置一個,也能夠 {[key]:[value]} 的形式配置多個es6

Output

指示webpack打包後的資源,輸出到哪裏去,以及如何命名。github

output的值是一個對象,指定了輸出文件名,和文件路徑,輸出文件建議使用 path模塊中的resolve即 resolve(__dirname,xxx)web

在webpack中輸出的文件名,若是你不想指定,能夠取使用[hash].擴展名的形式,webpack在輸出的時候,會自動指定hash值。面試

Loader

Webpack去處理那些非Javascript文件。(webpack自己只處理js和json數據)正則表達式

對應webpack的字段是 module,裏面指定了webpack各類的loader配置。形如

module: {
    rules: [
      {[key]:[value]}
    ]
  },
複製代碼

rules中的每個對象,對應着一個處理某個文件的模塊,爲了處理某種文件,咱們須要配置,匹配這個文件的正則表達式,形如 test:/具體正則表達式/ ,和經過 use:[loader-name] 的形式指定 多個loader,如:處理css 文件,咱們須要 style-loadercss-loader 。甚至有時候use數組裏面,不僅是 各個loader的名稱,可能還須要修改一些loader的配置,就會採起對象的形式指定loader,如給css添加兼容性處理的情景

同一文件各類loader的處理順序是自下而上的,css文件配置以下,文件會先通過 css-loader 處理,再通過style-loader處理。

module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          'style-loader',
          'css-loader',
        ]
      }
    ]
  },
複製代碼

上面引入的兩種loader都是直接經過loader名稱的形式引入的,按照對象的方式引入postcss-loader,對css作兼容性處理。

{
    test: /\.css$/,
    use: [
      'style-loader'
      'css-loader',
      {
        loader: 'postcss-loader',
        options: {
          ident: 'postcss',
          plugins: () => {
            require('postcss-preset-env')
          }
        }
      }
    ]
  },
複製代碼

固然最後要注意的是,這些loader都不是webpack,內置的,而是須要 經過npm 安裝。具體的插件安裝可看官網。建議你們和webpack有關的都安裝在 devDependencies 下 。

Plugins

各類功能強大的工具,包括打包優化和壓縮,甚至能夠從新定義環境中的變量。插件相比於Loader能夠作不少比Loader功能更強大的事。

插件和loader相同的是都須要先npm安裝,不一樣的是,loader不須要引入,可是要在use裏面寫一些配置。而插件則是經過,先require 引入某個插件,而後再在plugins,實例化引入的插件對象便可。若是須要修改插件的默認配置,在實例化的時候,以對象的形式傳入便可。

html 模板插件使用以下

const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
  entry: '......',
  output:'......',
  module:'......',
  plugins: [
    // 實例化require引入的插件 html-webpack-plugin
    //指定傳入的HTML模板是src目錄下的index.html文件
    new HtmlWebpackPlugin({
      template: './src/index.html'
    })
  ],
  mode: '.....'
}
複製代碼

Mode

模式分爲 development開發環境,production 生產環境。 這大概是webpack最簡潔的配置了,在production 模式下,會自動開啓壓縮js代碼和 tree shaking

在將來的 webpack5中,只有在 webpack.config.js 文件中指定一個mode,就可使用,上面的 entry,output 等配置,都變成了默認配置。

webpack打包過程

  1. 指定入口文件 entry
  2. webpack會根據入口文件裏面全部的依賴,造成依賴樹,而後會根據依賴樹中把因此須要的依賴引入,造成代碼塊(chunk),而後再根據不一樣的資源對應的loader,對代碼塊進行處理輸出爲 bundles.

處理css、less

npm install style-loader css-loader  -D
複製代碼

其中 css-loader 是爲了把 css 文件變成commonJS模塊,加載到JS中,style-loader是爲了在JS解析的時候能建立style標籤,把樣式整合到style標籤中,插入瀏覽器的head。

默認是有多少css,less 文件就會插入多少style標籤,每一個標籤就是對應的css代碼。

npm install less-loader -D 
複製代碼

安裝less-loader處理less文件,注意loader在代碼裏面配置順序是固定的,less文件必需要通過less-loader處理,才能被css-loader識別,同理最後才能被style-loader處理。

rules: [
      {
        test: /\.css$/,
        use: [
          // 從下到上運行loader
          // 建立style標籤,將js資源插入,添加到head生效
          'style-loader',
          // 將css 文件變成commonjs 模塊加載到js中,裏面內容 是樣式字符串。
          'css-loader',
        ]
      },
      {
        test: /\.less$/,
        use: [
          'style-loader',
          'css-loader',
          'less-loader'
        ]
      }
    ]
複製代碼

把css,less文件提取合併,而且壓縮一下造成單獨的css,再經過link標籤引入。目的是爲了把css儘快的提供給瀏覽器,而不是放在js中,致使瀏覽器須要先解析js才能獲取css,具體緣由見博客~瀏覽器,須要使用插件 mini-css-extract-plugin

const MiniCssExtractPlugin = require('mini-css-extract-plugin')
複製代碼

把css文件和less文件配置中的,style-loader都替換成 MiniCssExtractPlugin.loader,在plugins中實例化插件而且制定輸出文件路徑,完整配置以下

const { resolve } = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
  entry: "./src/index.js",
  output: {
    filename: 'js/build.js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
        ]
      },
      {
        test: /\.less$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          'less-loader'
        ]
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/public/index.html'
    }),
    // [hash:10]制定文件名稱取哈希值的前10位
    new MiniCssExtractPlugin({
      filename:"css/[hash:10].css"
    })
  ],
  mode: 'development'
}
複製代碼

壓縮css,感受就是去掉了css文件中的,空格註釋,也可能去掉了一些寫重複的樣式吧,反正就是爲了減小文件體積加快網絡傳輸速度。須要用到插件optimize-css-assets-webpack-plugin

npm install optimize-css-assets-webpack-plugin -D
複製代碼

這個插件使用比較簡單了,同樣須要引入

const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin')

....
  plugins: [
    ....,
    new OptimizeCssAssetsWebpackPlugin()
  ]
.... 
複製代碼

處理HTML、圖片、其餘靜態資源

npm install html-webpack-plugin -D
複製代碼

處理HTML文件須要使用 html-webpack-plugin,在plugins中實例化的時候,指定一下使用的模板,webpack會把輸出的js經過script標籤自動引入HTML中。

// webpack處理 HTML
const { resolve } = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
  entry: "./src/index.js",
  output: {
    filename: '/js/build.js',
    path: resolve(__dirname, 'build')
  },
  module: {
  },
  plugins: [
    new HtmlWebpackPlugin({
      //指定 src下的index.html 爲HTML基礎模板。
      template: './src/index.html'
    })
  ],
  mode: 'development'
}
複製代碼

處理圖片資源的時候使用的是loader名稱是url-loader,沒有photo-loader😁😁😁,固然還要下載file-loader,由於url-loader依賴於file-loader

npm install file-loader url-loader -D
複製代碼

具體配置以下,能夠解決commonJS import 圖片資源,和css,less文件中url裏面引用圖片資源的問題。

{
  test: /\.(jpg|png|gif|jpeg)$/,
  loader: 'url-loader',
  options: {
    // 圖片小於8kb時候會被base64處理
    limit: 8 * 1024,
    // 給圖片從新命名
    // ext 圖片原來擴展名稱
    name:'[hash:10].[ext]'
  }
},
複製代碼

若是還要處理HTML模板中引入圖片的問題還須要使用 html-loader, 此時要注意修改一下以前url-loader的配置,由於url-loader默認使用es6模塊化解析,而html-loader引入圖片是commonjs,解析時會出問題:[object Module],須要在url-loader配置文件中,關閉url-loader的es6模塊化,使用commonjs解析

npm install html-loader -D
複製代碼
{
  test: /\.(jpg|png|gif|jpeg)$/,
  loader: 'url-loader',
  options: {
    limit: 8 * 1024,
    // 解決:關閉url-loader的es6模塊化,使用commonjs解析
    esModule: false,
    name:'[hash:10].[ext]'
  },

},
{
  test: /\.html$/,
  loader: 'html-loader'
}
複製代碼

處理其餘靜態資源,好比字體圖標文件等,須要安裝file-loader,在以前安裝url-loader的時候已經安裝過file-loader了

{
   // exclude 排除 前面被處理過的 css/js/html資源
   // 其餘文件一概交給file-loader處理。
  exclude: /\.(css|js|html|less)$/,
  loader: 'file-loader',
  options: {
    name: '[hash:10].[ext]',
    // 指定其餘資源都輸出到static目錄下
    outputPath: 'static'
  }
}
複製代碼

css兼容性處理

面試的時候常常會被問到,瀏覽器兼容性問題,做爲一個學生,目前我開發都是使用Chrome和Firefox,處理瀏覽器兼容性問題,也就是webpack配置一下。 兼容css須要用插件postcss-loader,和插件的的配置postcss-preset-env(固然也可採用,autoprefixer規則取代postcss-preset-env規則)

npm install postcss-loader postcss-preset-env -D
複製代碼

安裝好插件,若是業務場景瀏覽器肯定,可採用中 package.json 增長browserslist,來肯定具體瀏覽器,至於browserslist的配置文件可看github

其中development,production 是指NodeJS環境(process.env.NODE_ENV),默認是production,而非webpack指定的mode。

{
  "xxx":"xxx",
  "devDependencies": "xxxx",
  "browserslist": {
    "development": [
      "last 1 version",
      "> 1%",
      "IE 10"
    ],
    "production": [
      "> 0.2%",
      "not dead",
      "not op_mini all"
    ]
  }
}
複製代碼

具體配置以下

const miniCssExtractPlugin = require('mini-css-extract-plugin')
//指定node環境爲 development
process.env.NODE_ENV = 'development'
module.exports = {
  entry: "...",
  output: "....",
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          miniCssExtractPlugin.loader,
          'css-loader',
          {
            loader: 'postcss-loader',
            options: {
              plugins: (loader) => [
                //也能夠採用
                // require('postcss-preset-env')()
                require('autoprefixer')()
              ]
            }
          }
        ]
      },
    ]
  },
  plugins:".....",
  mode: '.....'
}
複製代碼

devServer

配置devServer,至關於本地運行了一個NodeJS後來服務,須要安裝插件webpack-dev-server,此時webpack編譯的結果不會輸出在咱們指定的目錄下,由於dev-server不輸出文件,能夠想象成文件放內存中,node服務能夠訪問到,所以咱們手動刷新瀏覽器能夠看到正確結果。

npm install webpack-dev-server -D
複製代碼
module.exports = {
  ....,
  mode: '.....',
  devServer: {
    // 項目構建後路徑
    contentBase: resolve(__dirname, 'build'),
    // 啓動gzip壓縮
    compress: true,
    // 端口號
    port: 3000,
    // 自動打開瀏覽器
    open: true
  }
};
複製代碼

此時我建議在 package.jsonscript 腳本中寫入兩條腳本,分別用於以前的打包模式和開啓devServer 模式

{
  ....,
  "scripts": {
    ....,
    "build": "webpack",
    "build:prod": "webpack --mode=production",
    "dev": "webpack-dev-server --open",
  },
  ....
}
複製代碼

經過運行 npm run build 或者npm run build:prod 獲取以前相似的輸出,npm run dev 開啓webpack服務,此時還不支持熱更新和自動刷新瀏覽器,須要手動刷新,才能看到結果。

更多devServer看 官網配置

Javascript代碼兼容性

前面配置了css代碼的兼容性處理,可是JS代碼其實更須要兼容,JS不兼容可能就是沒法運行。處理JS兼容固然就是babel家族。babel官網

npm install @babel/cli @babel/core @babel/preset-env babel-loader -D

npm install @babel/plugin-transform-runtime  -D 

npm install @babel/plugin-proposal-class-properties -D

npm install @babel/runtime @babel/runtime-corejs2 --save
複製代碼

在項目根目錄編寫 babel.config.js 文件,寫入以下配置

module.exports = {
  "presets": [
       [
         "@babel/preset-env",
         //指定要兼容的瀏覽器,以及版本
         "targets": {
          "esmodules": true,
          "chrome": '60',
          "firefox": '60',
          "ie": '9',
          "safari": '10',
           "edge": '17'
          }
        ]
    ],
  "plugins": [
    ["@babel/plugin-transform-runtime", {
      "corejs": 2,
    }],
    "@babel/transform-arrow-functions",
    "@babel/plugin-proposal-class-properties"
  ]
}
複製代碼

在webpack.config.js中用babel處理js

module.exports={
  entry:"....",
  output:"....",
  module:{
    rules:[
      { 
        // 匹配js和jsx文件
        test: /\.tsx?$/,
        use: ["babel-loader"],
        //排除node_modules裏面的文件
        // 防止babel編譯了,node_modules裏面代碼包。
        exclude: [join(__dirname, "node_modules")]
      }
    ]
  },
}

複製代碼

上面的babel配置 (我用的是babel7的配置) 是我上次配置ts的,不知道會不會出錯,應該沒有問題, presets 裏面指定了target, core-js 部分沒問題,應該就能夠兼容ie。

我認爲 webpack最好的教程是來源與官網,這是我看了官網和網上找的一些視頻教程以後總結的一些基礎操做,詳細的配置可看 webpack官網~中文,本文中部分文字來源於尚硅谷的視頻,感謝尚硅谷老師的分享。【這不是廣告只是爲了聲明版權😂】

以上差很少就是 webpack的一些基本操做了,後面打算把webpack配置優化部分也補上,而後本身封裝一個腳手架,再加上一些ESLint的配置,歡迎你們持續關注 http://lemonlife.top 最近有點忙/(ㄒoㄒ)/~~

相關文章
相關標籤/搜索