webpack學習記錄(第一階段)

Webpack(>4.0.0)

第一階段

本質上,webpack 是一個現代 JavaScript 應用程序的靜態模塊打包工具。當 webpack 處理應用程序時,它會在內部構建一個 依賴圖(dependency graph),此依賴圖會映射項目所需的每個模塊,並生成一個或多個 bundle。

安裝

yarn add webpack webpack-cli -D

webpack可以0配置

  • 打包工具 -> 輸出後的結果(js模塊)
  • 默認打包出來的是production環境的文件
  • 支持模塊化打包(commonJs規範)

0配置打包

npx webpack

使用這句命令後,webpack-cli會在當前目錄下查找./src/index.js,然後將index.js打包默認輸出到./dist/main.js中。
使src>index.js\color{red}{*所以在使用該命令之前首先要有src -> index.js這樣的目錄結構}

手動配置打包

  • 默認配置文件名稱爲webpack.config.js,此文件是Node執行,所以語法規範要符合Node的語法規範。文件存放在執行命令的同級目錄。可以使用自定義名稱,但是打包命令就必須指向此文件。
npx webpack --config [webpack配置文件]
  • 在package.json文件中配置腳本命令
...
"scripts": {
  "build": "npx webpack"
},
...

然後可使用npm run build或者yarn build。主要看自己習慣哪一個包管理器。

開發服務(服務器插件)

開啓服務器打包時,打包後的結果生成在內存中,方便預覽。

yarn add webpack-dev-server -D

0配置啓動後會生成以當前路徑的靜態目錄
webpack.config.js中的常用配置:

devServer: { // 開發服務器配置
  port: 3000,
  progress: true, // 進度條 
  open: false, // true -> 自動打開瀏覽器
  contentBase: './build', // 靜態服務文件目錄
  compress: true, // gzip壓縮
},

處理html文件

yarn add html-webpack-plugin -D

webpack.config.js中的常用配置:

plugins: [ // 引用插件
  new HtmlWebpackPlugin({
    template: './src/index.html', // 指定html模板
    filename: 'index.html', // 生成的文件名
    hash: true, // 添加hash戳
    minify: { // 打包配置
      removeAttributeQuotes: true, // 去除雙引號
      collapseWhitespace: true, // 清除空格,成爲一行
    },
  })
]

處理css樣式文件

yarn add style-loader css-loader -D

webpack.config.js中的基礎配置:

module: { // 模塊配置
  /**
    * loader執行的順序爲從右到左、從下到上執行
    * loader的引入可以是數組,可以是字符串
    */
  rules: [ // 引入模塊規則
    {
      test: /\.css$/,
      use: [
        {
          loader: 'style-loader', // 可以解決將樣式插入到html文件中
          options: { 
            insert: function insertAtTop(element) { // 將打包的css
              var parent = document.querySelector('head');
              var lastInsertedElement =
                window._lastElementInsertedByStyleLoader;
              if (!lastInsertedElement) {
                parent.insertBefore(element, parent.firstChild);
              } else if (lastInsertedElement.nextSibling) {
                parent.insertBefore(element, lastInsertedElement.nextSibling);
              } else {
                parent.appendChild(element);
              }
              window._lastElementInsertedByStyleLoader = element;
            },
            injectType: 'singletonStyleTag' // 將所有樣式打包到一個style標籤中
          }
        }, 
        'css-loader' // 主要解決@import問題
      ]
    },
    { // stylus 模塊配置
      test: /\.styl$/,
      use: [
        {
          loader: 'style-loader',
          options: {
            injectType: 'singletonStyleTag'
          }
        }, 
        'css-loader',
        'stylus-loader'
      ]
    }
  ]
}

webpack.config.js中的打包優化配置(抽離樣式):
需要用到下面四個插件

yarn add mini-css-extract-plugin optimize-css-assets-webpack-plugin terser-webpack-plugin autoprefixer -D

webpack.config.js壓縮配置:

const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const TesterWebpackPlugin = require('terser-webpack-plugin')
const OptimizeCssPlugin = require('optimize-css-assets-webpack-plugin')
module.exports = {
  optimization: { // 優化項
    minimizer: [ // 壓縮
      new OptimizeCssPlugin(), // 壓縮css,會覆蓋webpack對js的壓縮
      new TesterWebpackPlugin({ // 解決OptimizeCssPlugin對壓縮覆蓋js問題
        cache: true, // 支持緩存
        parallel: true, // 併發打包,同時壓縮多個文件
      }),
    ]
  },
  ...
   plugins: [ // 引用插件
    new MiniCssExtractPlugin({ // 抽離樣式表爲單獨的一個文件
      filename: 'main.css',
    })
  ],
  module: { // 模塊配置
    /**
     * loader執行的順序爲從右到左、從下到上執行
     * loader的引入可以是數組,可以是字符串
     */
    rules: [ // 引入模塊規則
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader, // 生成單獨的一個樣式文件,放在head的最末尾
          'css-loader', // 主要解決@import問題
          'postcss-loader', // 解決瀏覽器前綴
        ]
      },
      {
        test: /\.styl$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          'postcss-loader',
          'stylus-loader'
        ]
      }
    ]
  },
  ...
}

package.json文件配置:

用於支持postcss和autoprefixer組合,解決自動添加瀏覽器前綴問題

"devDependencies": {
  ...
},
"browserslist": [
  "defaults",
  "not ie <= 8",
  "last 2 versions",
  "> 1%",
  "iOS >= 7",
  "Android >= 4.0"
]

ES6/ES7/提案語法轉換成低版本兼容語法

yarn add babel-loader @babel/core @babel/plugin-transform-runtime -D
yarn add @babel/runtime --save

ES6轉換配置:

...
rules: [ // 引入模塊規則
    ...
    {
      test: /\.js$/,
      use: { 
        loader: 'babel-loader',// 處理高版本語法轉低版本語法
        options: {
          presets: [
            '@babel/preset-env' // 可以使用最新的js語法
          ],
          plugins: [
            // 處理生成器等一些高級內置語法
            "@babel/plugin-transform-runtime"
          ]
        }
      },
      include: path.resolve(__dirname, 'src'), // 只轉換此文件夾下的js,絕對路徑
      exclude: /node_modules/ // 排除該文件夾下的轉換
    },
    ...
...

ES7轉換支持:

yarn add @babel/plugin-proposal-decorators @babel/plugin-proposal-class-properties -D
yarn add @babel/polyfill --save

配置:

...
rules: [ // 引入模塊規則
    ...
    {
      test: /\.js$/,
      use: { 
        loader: 'babel-loader',// 處理高版本語法轉低版本語法
        options: {
          presets: [
            '@babel/preset-env' // 可以使用最新的js語法
          ],
          plugins: [
            // 處理ES7中的裝飾器轉換
            ["@babel/plugin-proposal-decorators", { "legacy": true }],
            // 處理ES7中的類轉換
            ["@babel/plugin-proposal-class-properties", { "loose" : true }],
            // 處理生成器等一些高級內置語法
            "@babel/plugin-transform-runtime"
          ]
        }
      },
      include: path.resolve(__dirname, 'src'), // 只轉換此文件夾下的js,絕對路徑
      exclude: /node_modules/ // 排除該文件夾下的轉換
    },
    ...
...

在入口文件引入@babel/polyfill文件:
index.js

require('@babel/polyfill')

語法校驗(eslint)

yarn add eslint eslint-loader -D

webpack.config.js配置:

...
rules: [ // 引入模塊規則
    {
      test: /\.js$/,
      enforce: 'pre', // 在位置上的下一個rules前執行
      loader: 'eslint-loader',
      include: path.resolve(__dirname, 'src'),
      exclude: /node_modules/,
      options: {
        cache: true // 緩存
      }
    },
    ...
]
...

在項目根目錄添加.eslintrc.json

{
	"parserOptions": {
		"ecmaVersion": 6,
		"sourceType": "module",
		"ecmaFeatures": {}
	},
	"rules": {
		"space-before-function-paren": 2,
    ...
	},
	"env": {}
}

全局變量引入

import $ from 'jquery'
console.log($) // func...
console.log(window.$) // undefined 打包後形成了閉包導致沒有掛到window上

使用expost-loader的方式暴露到window上

import $ from 'expose-loader?$!jquery' // 內聯loader的使用方式:[loader名稱]?[字符串變量名稱]![包名]

使用配置的方式
只要是使用了expose-loader,無論哪種方式都必須將要暴露的模塊引入一次
boundle.js

require(jquery) 

// 方式1

// webpack.config.js
rules: [
  {
    test: require.reslove('jquery'),
    loader: 'expost-loader?$'
  }
]

方式2

// webpack.config.js
rules: [
  {
    test: require.resolve('jquery'),
    use: [{
      loader: 'expose-loader',
      options: '$'
    },
    // 多暴露
    {
      loader: 'expose-loader',
      options: 'jQuery'
    }]
  },
]

方式3,在每個模塊注入對象

// webpack.config.js
// 不需要(在boundle.js)引入需要暴露的模塊
const Webpack = require('webpack')
...
plugins: [
  // 模塊注入變量
  new Webpack.ProvidePlugin({
    $: 'jquery'
  }) 
]

方式4,使用CDN引入且在模塊中引用的時候不要打包此文件
index.html

<html>
<head>
  <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
</head>
<body></body>
</html>
// webpack.config.js
...
module.exports = {
  plugins: [...],
  externals: {
    jquery: '$' // 不打包jquery模塊
  },
  module: {...}
}

打包圖片

  • 在css中引入圖片是默認支持的,由css-loader處理
  • 在js中引入圖片需要file-loader支持
yarn add file-loader -D // 使用頻率低
yarn add url-loader -D // 使用頻率高(file-loader的增強版)
  • 在html中引入圖片需要html-withimg-loader支持
yarn add html-withimg-loader -D

webpack.config.js配置

rules: [
  // html中引入圖片處理
  {
    test: /\.html$/,
    loader: 'html-withimg-loader'
  },
  // 默認使用ES模塊語法的JS模塊,生產中使用頻率不高
  // {
  //   test: /\.(jpg|png|svg|jpeg|gif)$/,
  //   use: {
  //     loader: 'file-loader', 
  //     options: {
  //       esModule: false // 關閉ES模塊語法,不然會與// html-withimg-loader衝突
  //     }
  //   }
  // },
  // js中引入圖片處理,file-loader的增強版
  {
    test: /\.(jpg|png|svg|jpeg|gif)$/,
    use: {
      loader: 'url-loader',
      options: {
        limit: 200 * 1024, // 當圖片小於200k是使用base64編碼,減少對服務器的請求
        esModule: false // 關閉ES模塊語法,不然會與html-withimg-loader衝突
      } 
    }
  },
  ...
]

資源分類打包

將不同的文件分類放在不同的文件夾中,然後使用publicPath設置公共資源路徑,設置資源路徑的時候,可以在output配置項中添加,將會作用到全部的文件,在不同的文件中配置publicPath則就是針對這一模塊的資源路徑,單獨配置的權重大於公共配置的權重。
webpack.config.js

// 統一配置
module.exports = {
  ...
  output: {
    publicPath: 'http://wlittleyang.com'
  }
  ...
}
  • js
module.exports = {
  ...
  output: {
    filename: 'script/bundle.[hash:6].js', // 輸出到script文件夾中
  }
  ...
}
  • css
plugins: {
  new MiniCssExtractPlugin({ // 抽離樣式表爲單獨的一個文件
    filename: 'css/main.css', // 將css文件打包到css目錄下
  }),
}
  • 圖片
// 在url-loader下配置 outputPath: '/images/',
{
  test: /\.(jpg|png|svg|jpeg|gif)$/,
  use: {
    loader: 'url-loader',
    options: {
      limit: 200 * 1024, // 當圖片小於200k是使用base64編碼,減少對服務器的請求
      esModule: false, // 關閉ES模塊語法,不然會與html-withimg-loader衝突
      outputPath: '/images/', // 將圖片打包到images目錄下
      publicPath: 'http://baidu.com' // 單獨添加公共路徑,如CDN,單獨的會覆蓋統一的
    } 
  }
},
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章