webpack4配置基礎

前言

爲何要使用構建工具?

1.轉換ES6語法(不少老版本的瀏覽器不支持新語法) 2.轉換JSX  3.CSS前綴補全/預處理器  4.壓縮混淆(將代碼邏輯儘量地隱藏起來)  5.圖片壓縮  6. ....javascript

爲何選擇webpack?

  1. 社區生態豐富
  2. 配置靈活、插件化擴展
  3. 官方更新迭代速度快

基礎概念

默認的配置文件是weback.config.js,在package.json中配置腳本能夠經過webpack --config來指定構建使用的配置文件。css

初始化

建立並進入新的目錄,執行以下命令,初始化package.json文件,這是一個模塊的描述文件,-y的意思是全部配置都是yeshtml

npm init -y

安裝webpack前端

npm install webpack webpack-cli --save-dev

核心概念

先看一下一份最簡單的webpack配置是什麼樣的html5

const path = require('path');

module.exports = {
   entry: './src/index.js',  // 打包的入口文件
   output: {    // 打包後的輸出
      filename: "bundle.js",
      path: path.join(__dirname, "/dist")
   },
   mode: 'development', // 所處環境
   module: {
      rules: [
         {
            test: /\.js$/,
            use: "babel-loader"
         },
         ......
      ]
   },
   plugins: [
      new HtmlWebpackPlugin(),
   ]
};

entryjava

打包的入口文件 node

單入口:react

entry: "./src/index.js"

多入口(適用於多頁面場景):webpack

entry: {
    app: "./src/app.js",
    adminApp: "./src/adminApp.js",
}

outputios

打包以後的輸出

單輸出:

output: {
    filename: "bundle.js",
    path: __dirname + "/dist" 
}

多輸出:

output: {
    filename: "[name].js", // 佔位符[name]表明entry中的key
    path: __dirname + "/dist"
}

Loaders

webpack只支持JS和JSON兩種文件類型,要想支持其餘文件類型且轉化成有效的模塊,須要經過Loaders。Loaders自己是一個函數,接收源文件作參數,返回轉換的結果。

常見的Loaders

babel-loader   轉換ES6/ES7等語法
css-loader     支持.css文件的加載和解析
less-loader    將less文件轉換成css
ts-loader      將TS轉換成js
file-loader    將圖片、字體等的打包
raw-loader     將文件以字符串的形式導入
thread-loader  多線程打包JS和CSS

Plugins

插件用於打包文件的優化,資源管理和環境變量注入,做用於整個構建過程。也能夠理解爲Loaders沒法完成的事情均可以用Plugins完成。

常見的Plugins:

CommonsChunkPlugin        經常使用於多頁面打包狀況下,將多個頁面公用的js代碼塊提取成公共js
CleanWebpackPlugin        清理構建目錄
ExtractTextWebpackPlugin  將CSS從bundle文件裏提取成一個獨立的CSS文件
CopyWebpackPlugin         將文件或文件夾拷貝到夠賤的輸出目錄
HtmlWebpackPlugin         建立html文件去承載輸出的bundle。這個很是有用,不須要咱們手動去建立html文件
UglifyjsWebpackPlugin     壓縮JS
ZipWebpackPlugin          將打包的資源生成一個zip包

mode

用來指定當前的構建環境,值有 production 、development 、none,默認是production。經過mode可使用webpack內置的函數和功能:

developement

開啓 NamedChunksPlugin 和 NamedModulesPlugin 在代碼熱更新階段,打印哪一個模塊發生了更新

production

開啓 FlagDependencyUsagePlugin , FlagIncludedChunksPlugin , ModuleConcatenationPlugin , NoEmitOnErrorsPlugin,OccurrenceOrderPlugin , SideEffectsFlagPlugin 和 TerserPlugin

none

不開啓任何優化

webpack基礎功能

解析ES6

使用babel-loader, babel的配置文件是.babelrc, 增長ES6的babel preset配置

1.安裝包

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

2.建立.babelrc文件,並添加配置

{
  "presets": [
    "@babel/preset-react",
    "@babel/preset-env"
  ]
}

3.webpack.config.js配置

module: {
      rules: [
         {
            test: /\.js$/,
            use: "babel-loader", // 用來解析ES6
         },
      ]
},

解析JSX

增長babel preset配置:

"@babel/preset-react"

要在React中使用箭頭函數,須要安裝插件

npm i @babel/plugin-proposal-class-properties
// .babelrc
"plugins": [
    "@babel/plugin-proposal-class-properties"
]

解析CSS/CSS預處理/前綴補全

less-loader   將less轉化成css
css-loader    讓webpack解析css文件,並轉換成commonjs對象,插入到JS裏(由於webpack自己只支持js和json)
style-loader  將樣式經過<style>標籤插入到<head>中

CSS前綴常見的有: -ms -moz -webkit -o 須要安裝autoprefixer 和 postcss-loader

npm i autoprefixer postcss-loader

配置:

{
   test: /\.less$/,
   use: [
      "style-loader",
      "css-loader",
      {
         loader: "postcss-loader",
         options: {
            plugins: () => [
               require('autoprefixer')({
                  overrideBrowserslist: ['last 2 version', '>1%', 'ios 7'] // 指定所須要兼容瀏覽器的版本
               })
            ]
         }
      },
      "less-loader",
   ]
},
執行順序:less-loader -> postcss-loader -> css-loader -> style-loader

解析圖片、字體

file-loader 用於處理文件

 js文件中:

import logo from './images/geektime.png'
const MyComponent = () => {
    retrun <img alt="" src={logo} />
}

webpack.config.js配置:

{
   test: /.(png|jpg|gif|jpeg)$/i,
   use: {
      loader: "file-loader",
      options: {
         name: '[name][hash:8].[ext]'  // 重命名打包後的文件
      }
   }
}

不少時候,前端的圖片請求路徑須要從後端接口獲取,不適用此場景。另外,即便不從後端獲取,靜態資源也能夠用傳統的相對路徑引用,此時存在一個問題,就是打包後的文件夾,與打包前源文件位置不一樣,相對靜態文件的相對路徑也不一樣,形成打包後路徑失效,沒法引入的狀況。咱們須要將靜態文件夾總體複製到打包後的文件目錄內,手工作太麻煩,能夠藉助插件實現。

npm i copy-webpack-plugin

 webpack.config.js配置:

const CopyWebpackPlugin = require('copy-webpack-plugin');
plugins: [
      new CopyWebpackPlugin([
         {
            from: './src/static',
            to: __dirname + './dist/static'
         }
      ])
]

資源解析

url-loader 也能夠處理圖片和字體,能夠設置較小資源自動 base64。

webpack.config.js配置:

{
   test: /\.(png|svg|jpg|gif)$/,
   use: [
      {
         loader: "url-loader",
         options: {
            limit: 1024*5,  // 當文件小於1024*n字節,webpack將該資源自動轉化成base64編碼在js文件中
         }
      }
   ]
}

文件監聽

文件監聽指在發現源代碼發生變化時,自動從新構建出新的輸出文件。須要手動刷新瀏覽器。

webpack開啓監聽模式有兩種方式:

  • 命令打包時帶上 --watch參數(能夠在package.json中配置腳本)
  • 配置webpack.config.js中設置 watch: true

webapck配置:

watch: true,
watchOptions: {
   ignored: /node_modules/,   // 不監聽的文件或文件夾,默認爲空。正則匹配/字符串均可
   aggregateTimeout: 300,     // 監聽到變化發生後,延遲300ms再去執行,默認300ms
   poll: 1000              // 輪詢頻率,默認每秒1000次
},

監聽原理:輪詢判斷文件的最後編輯時間是否發生變化。某個文件發生了變化,並不會當即告訴監聽者,而是先緩存起來,等aggregateTimeout時間事後再構建。

熱更新

須要安裝webpack-dev-server,適用於開發環境,不輸出文件,將構建後的內容保存在內存中。

在package.json中編寫腳本:

"dev": "webpack-dev-server --open"   // open指自動打開瀏覽器

webpack配置:

devServer: {
   contentBase: './dist',   // 必需
   port: 8080,  // 默認8080
   hot: true   // 默認true
},

固然,若是使用html-webpack-plugin,則不須要contentBase屬性。

文件指紋策略

做用:

  1. 作版本管理。當文件發生修改時,只須要更新發生變化的文件
  2. 瀏覽器緩存。文件名發生變化時,瀏覽器會從新請求該文件,而其它未改變的文件則直接從緩存中拿就行。

三種hash:

  • Hash:和整個項目的構建相關,只要項目文件有修改,整個項目構建的hash值就會改變
  • Chunkhash:和webpack打包的chunk有關,不一樣的entry會生成不一樣的chunkhash值,只能在生產環境中使用
  • Contenthash:根據文本內容來定義hash,文件內容不變,則contenthash不變

使用:

entry: {
    app: './src/app.js',
    search: './src/search.js',
},
output: {
    filename: '[name][chunkhash:8].js', 
    path: __dirname + '/dist'
}

CSS因爲style-loader的存在,被內聯在html中,能夠用插件將其獨立出一個css文件。

npm install mini-css-extract-plugin

const MiniCssExtractPlugin = require('mini-css-extract-plugin');
plugins: [
    new MiniCssExtractPlugin({ // 該插件會將css提取出來並在html中引入獨立的文件,與style-loader互斥
        filename: '[name][contenthash:8].css'
    });
]

JS文件只能使用hash和ChunkHash,CSS建議使用ContentHash

佔位符:
[ext]   後綴名
[name]  文件名稱
[path]  文件的相對路徑
[folder] 文件所在的文件夾
[contenthash]  文件的內容hash,默認是md5生成
[hash]      文件內容的hash,默認md5生成(注意這裏的hash與前面的"hash"意義不同)
[emoji]     一個隨機的只帶文件內容的emoji

文件壓縮

主要是HTML、CSS、JS的壓縮

JS壓縮:

  webpack內置了uglifyjs-webpack-plugin,在生產環境自動實現了JS壓縮

CSS壓縮:

  使用optimize-css-assets-webpack-plugin 和 cssnano能夠實現對CSS文件進行壓縮,由於style-loader將CSS內聯在html中,須要藉助 mini-css-extract-plugin 插件將CSS分離成文件。

HTML壓縮:

  html-webpack-plugin設置壓縮參數minify,能夠將空格、換行和註釋幹掉

npm install html-webpack-plugin optimize-css-assets-webpack-plugin cssnano mini-css-extract-plugin

const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
// 一個頁面對應一個 html-webpack-plugin
module: {
      rules: [
         {
            test: /\.less$/,
            use: [
               // "style-loader",
               MiniCssExtractPlugin.loader, // 與style-loader互斥
               "css-loader",
               {
                  loader: "postcss-loader",
                  options: {
                     plugins: () => [
                        require('autoprefixer')({
                           overrideBrowserslist: ['last 2 version', '>1%', 'ios 7'] // 指定所須要兼容瀏覽器的版本
                        })
                     ]
                  }
               },
               "less-loader",
            ]
         },
      ]
},
new HtmlWebpackPlugin({
   template: "./src/index.html", // 模板所在路徑
   filename: "index.html", // 指定打包後的文件名稱
   // chunks: [''], // 生成的html要鏈入哪些js文件。數組值對應的是entry中的鍵
   // inject: true,  // 將生成的css等文件自動注入到html內,默認開啓
   minify: {
      html5: true,
      collapseWhitespace: true,   // 幹掉空格
      preserveLineBreaks: false,  // 幹掉換行
      minifyCSS: true,      // 壓縮html內的css
      minifyJS: true,       // 壓縮html內的js
      removeComments: true, // 刪除註釋
   },
}),
new MiniCssExtractPlugin({
   filename: '[name][contenthash:8].css'
}),
new OptimizeCssAssetsPlugin({
   assetNameRegExp: /\.css$/g,
   cssProcessor: require('cssnano'),
}),

自動清理構建目錄

藉助 clean-webpack-plugin 每次構建都會自動刪除以前的構建目錄。默認會刪除output指定的輸出目錄。

const { CleanWebpackPlugin } = require('clean-webpack-plugin');
new CleanWebpackPlugin(),
相關文章
相關標籤/搜索