輕松搞定webpack5.x


源碼地址:https://gitee.com/cyp926/webpack-project.git
"webpack": "^5.46.0",
"webpack-cli": "^4.7.2",

一、webpack

1.1 webpack是什么

webpack是一種前端資源構建工具,一個靜態模塊打包器.在webpack看來,前端的所有資源文件(js/json/css/image/less/sass...)都會作為模塊處理。它將根據模塊的依賴關系進行靜態分析,打包生成對應的靜態資源
配置文件: webpack.config.js

1.2 五個核心內容

  • entry:入口。webpack是基於模塊的,使用webpack首先需要指定模塊解析入口(entry),webpack從入口開始根據模塊間依賴關系遞歸解析和處理所有資源文件。
  • output:輸出。源代碼經過webpack處理之后的最終產物。
  • loader:模塊轉換器。本質就是一個函數,在該函數中對接收到的內容進行轉換,返回轉換后的結果。因為 Webpack 只認識 JavaScript,所以 Loader 就成了翻譯官,對其他類型的資源進行轉譯的預處理工作。
  • plugin:擴展插件。基於事件流框架 Tapable,插件可以擴展 Webpack 的功能,在 Webpack 運行的生命周期中會廣播出許多事件,Plugin 可以監聽這些事件,在合適的時機通過 Webpack 提供的 API 改變輸出結果。
  • mode 模式。通過選擇 development 或 production 之中的一個,來設置 mode 參數,你可以啟用相應模式下的 webpack 內置的優化

1.3 下載webpack的插件

npm init -y
npm i -D webpack webpack-cli

1.4 基本使用

const path = require('path')
module.exports = {
   // https://webpack.docschina.org/configuration/mode/
  // 打包模式  development |  production
  mode: 'development',
  // 項目入口
  entry: './src/index.js',
  // 項目出口
  output: {
        path: path.resolve(path.dirname(__dirname), 'dist'),
        // js/打包的位置, [name]默認的名稱為main ,-[hash:8] 拼接hash
        filename: 'js/[name]-[hash:8].js'
  }
}

運行打包命令行

  • npx webpack
  • npx webpack --mode development (不寫配置情況下)
  • npx webpack 需要打包的文件 -o 打包的文件位置與名稱 --mode development (不寫配置情況下)

快捷配置

我們可以直接在package.json中配置:"build":"webpack"

1.5 打包html

  • 安裝:html-webpack-plugin
1)引入
const HtmlWebpackPlugin = require('html-webpack-plugin')

2)打包壓縮html(打包多個,就實例化new多個)
plugins: [
    new HtmlWebpackPlugin({
        title: '歡迎來到Webpack',打包設置標題 (可選項)
        template:'./src/index.html', //打包的文件
        filename:'demo.html',     //打包后的名稱 (可選項)
        chunks:[],               //指定html中使用的js文件 (可選項)
        minify:{                  //壓縮 (可選項)
            // 移除空格
            collapseWhitespace:true,
            // 移除注釋
            removeComments:true,
        }
    }),
]

3)模板中使用定義的title
<title><%= htmlWebpackPlugin.options.title %></title>

1.6 開發服務器 devServer

  • npm i -D webpack-dev-server@3 (注意這里我們用到的是3版本的)
  • 命令 npx webpack serve
 // 在webpack5 需要加上這個選項才會自動刷新頁面
target:"web"

配置devServer

 devServer:{

        contentBase: path.resolve(__dirname, '../dist'),// 運行代碼目錄(可選)  
        port:3001, //端口號   
        compress:true,//自動更新 (可選)  
        open:true//自動打開瀏覽器 (可選)  
        watchOptions: { ignored: /node_modules/}, // 忽略文件 (可選) 
        host: 'localhost', // 域名(可選) 默認就是localhost
        clientLogLevel: 'none', // 不要顯示啟動服務器的日志信息
        overlay: false,  // 如果出錯,不要全屏提示
        // 服務器代理 --> 解決開發環境跨域問題
        proxy: {
        // 一旦devServer服務器接受到 /api開頭的請求,就會把請求轉發到另一個服務器
        '/api': {
            target: 'http://localhost:3000',
            // 發送請求時,請求路徑重寫: 將/api 去除
            pathRewrite: {
            '^/api': ''
            }
        }
        }
    }

package.json中的scripts中配置命令

"serve": "webpack-dev-server --config ./config/webpack.config.js"

1.7 打包css,sass等樣式

1.7.1 打包css

webpack默認只支持js的打包,不支持其它類型,為了讓它支持樣式的打包就需要加載一些loader

  • npm i -D css-loader style-loader
   /* 
        一個用    loader:css-loader
        一個以上  use:[]
        從右往左
    */
    module:{
        rules:[
        
            {
                test: /\.css$/,
                use: ['style-loader','css-loader']
            }
        ]
    }

1.7.2 打包less或者sass

  • less npm i -D less-loader
 {
    test: /\.less$/,
    use: [
        'style-loader',
        'css-loader',
        'less-loader'
    ]
}
  • sass npm i -D node-sass sass-loader
 {
    test: /\.sass$/,
    use: [
        'style-loader',
        'css-loader',
        'sass-loader'
    ]
}

1.7.3 提取抽離css為單獨文件

  • npm i -D mini-css-extract-plugin
const miniCssExtractPlugin = require('mini-css-extract-plugin')
module:{
    rules:[
        {
            test: /\.css$/,
            use: [
                miniCssExtractPlugin.loader, //寫在第一行
                'css-loader']
        },
         {
            test: /\.css$/,
            use: [
                miniCssExtractPlugin.loader, //寫在第一行
                'css-loader',
                'sass-loader'
                ]
        },
    ]
},
plugins:[
  new miniCssExtractPlugin({filename:'demo.css'})
]

1.7.4css3兼容處理(變異成各個瀏覽器支持的---前綴--)

  • npm i -D postcss-loader postcss-preset-env
  1. package.json配置兼容瀏覽器
  "browserslist": [
    ">0.2%",
    "last 2 version",
    "not dead"
  ]
  1. 新建文件postcss.config.js
module.exports={
    plugins:[
     require('postcss-preset-env')()   
    ]
}
  1. 引入loader
{
    test: /\.css$/,
    use: [
        miniCssExtractPlugin.loader,
        'css-loader',
        'postcss-loader'
    ]
},

1.7.5 壓縮css

  • npm i -D optimize-css-assets-webpack-plugin
plugins:[
    new optimizeCssAssetsWebpackPlugin()
]

1.7.6 css去掉無用的代嗎

  • npm i -D purgecss-webpack-plugin
new PurgecssWebpackPlugin({
    paths:glob.sync(pattern:`${PATH.src}/**/*`,options:{nodir:true})
})

1.8 webpack打包資源

  • npm i -D url-loader file-loader html-loader

1.8.1 背景圖打包

module: {
  rules: [
        {
            test: /\.(png|jpeg|jpg|gif)$/,
            loader: 'url-loader',
            options: {
                publicPath:'./images/',
                outputPath: 'imgs/',
                name:'[name][hash].[ext]',//命名hash+名稱
                limit:1024*8,//限制8k一下轉base64
            }
        },
         // 也可以這么寫圖片處理
        {
        test: /\.(png|jpeg|jpg|gif)$/,
        use: [
            {
            loader: 'url-loader',
            options: {
                // 圖片小於8kb,就會被base64處理
                // 優點: 減少請求數量(減輕服務器壓力)
                // 缺點:圖片體積會更大(文件請求速度更慢)
                limit: 8 * 1024,
                name: 'static/imgs/[name].[ext]',
                publicPath: '/dist'
            }
            }
        ]
        },
    ]
}

1.8.2 html圖 html-loader

module: {
  rules: [
    {
        test: /\.(html)$/,
        loader: 'html-loader',
    }
  ]
}

1.8.3 其他文件打包

像項目中字體資源是不需要進行打包處理的,可以直接的通過復制方式給打包到目標目錄中

module: {
  rules: [
        {
            // exclude 排查資源
            exclude:/\.(js|json|html|css|less|scss|png|jpg)$/,
            loader:'file-loader',
            options:{
                outputPath: 'font/', //打包位置
                publicPath:'./font', //尋找位置
                name:'[name][hasg].[ext]',//命名hash+名稱
            }
        }
    ]
}
  • 也可以這樣處理靜態資源
    • npm i -D copy-webpack-plugin
    const CopyPlugin = require('copy-webpack-plugin')
    plugins: [
        new CopyPlugin({
            patterns: [
                {
                    // 來源
                    from: path.resolve(__dirname, '../src/iconfont/'),
                    // 目標
                    to: path.resolve(__dirname, '../dist/iconfont')
                },
                 {
                    // 來源
                    from: path.resolve(__dirname, '../src/iconfont/'),
                    // 目標
                    to: path.resolve(__dirname, '../dist/iconfont')
                }
            ]
        })
    ]
    

1.9 eslint代碼規范(airbnb)

  • npm i -D eslint-loader eslint eslint-config-airbnb-base eslint-plugin-import
  1. package.json
 "eslintConfig":{
      "extends":"airbnb-base"
  }
  1. webpack.config.js
{
    test: /\.js$/,
    //只檢查自己寫的代碼,不檢查第三方的
    exclude:/node_modules/,
    loader:'eslint-loader'
},

1.10 js兼容處理

webpack在不需要引入任何loader可以對於js進行打包處理,但是它不會對於js兼容性進行任務的處理,而我們編寫的項目是需要在不同的瀏覽器中運行的,此時就需要對於js的兼容性在打包過程中進行對應的處理。使用babel來完成對應的js兼容處理

  • npm i -D babel-loader @babel/core @babel/preset-env core-js@3
module: {
  rules: [
    // js兼容處理
    {
      test: /\.js$/,
      // 排除
      exclude: /node_modules/,
      loader: 'babel-loader',
      options: {
        presets: [
          [
            '@babel/preset-env',
            {
              // 按需加載  inital  enter uage
              useBuiltIns: 'usage',
              // 指定core-js版本
              corejs: 3,
              // 兼容性做到哪個版本的瀏覽器
              targets: {
                chrome: '80',
                firefox: '50',
                ie: '9',
                safari: '10',
                edge: '17'
              }
            }
          ]
        ]
      }
    }
  ]
}

二、環境優化

開發環境

- 打包構建速度
- 優化代碼調試

生產優化(樹搖)

- 代碼運行性能

HMR模塊熱替換

 devServer:{
    port:3001,
    compress:true,//自動更新
    open:true,//自動打開瀏覽器
    hot:true//HMR模塊熱替換
}

樹搖去掉沒用到的js代碼

  • tree-shaking webpack自帶
  1. es6 導出
  2. 必須是 production

可以:在package.json文件中添加了 "sideEffects": false 表示所有代碼都沒有副作用(所有代碼都可以進行tree shaking)

問題:可能會把 css的@babel/polyfill (副作用)文件刪除掉
解決:"sideEffects":["*.css"]

css去掉無用的代嗎

  • npm i -D purgecss-webpack-plugin
new PurgecssWebpackPlugin({
    paths:glob.sync(pattern:`${PATH.src}/**/*`,options:{nodir:true})
})

代碼分割

1、通過配置入口文件來進行分割包,這是最簡單和最直接的方式,但是這種方式有一定缺點,可能造成重復引用的模塊重復被打包;

2、使用splitChunksPlugin來進行公共模塊的提取(被optimizition.splitchunk取代);

3、通過動態代碼加載來分割代碼,使用import()方法,調用import() 之處,被作為分離的模塊起點,意思是被請求的模塊和它引用的所有子模塊,會分離到一個單獨的 chunk 中;

entry多入口實現分割

entry: {
    main: './src/js/index.js',
    print: './src/js/print.js'
},
output: {
    filename: "js/[name]-[contentHash].js",
    path: path.resolve(__dirname, "dist")
}

optimization配置實現分割

  • 過大的js文件拆分成多個,實現並行加載,提高加載速度(把工具庫jq,lodash和業務邏輯拆分開)

可以將node_modules中代碼單獨打包一個chunk最終輸出
chunks: 表示顯示塊的范圍,有三個可選值:initial(初始塊 同步)、async(按需加載塊)、all(全部塊),默認為all;

optimization: {
    splitChunks: {
      chunks: 'all'
    }
},

externals忽略不打入的包

例如項目中使用從 CDN 引入 jQuery,而不是把它打包進來使用

externals: {
  jquery: 'jQuery'
}

image

路徑別名與導入后綴省略

  // 解析模塊的規則
  resolve: {
    // 配置解析模塊路徑別名:優點簡寫路徑,缺點路徑沒有提示
    alias: {
      // 定義一個@變量,可在import引入時使用
      '@': path.resolve(__dirname, '../src')
      '$css': path.resolve(__dirname, '../src/css')
    },
    // 配置省略文件路徑的后綴名稱 import '@/index'
    // 如果省略,建議文件名稱不要重名了
    extensions: ['.js', '.json', '.vue']
  }

Source Maps調試配置

作為開發,代碼調試當然少不了,那么問題來了,經過打包后的文件,你是不容易找到出錯的地方的,Source Map就是用來解決這個問題的。

devtool: 'source-map'  // 會生成對於調試的完整的.map文件,但同時也會減慢打包速度

三、代碼

相關代碼

webpack.config.js

// 采用commonjs
const path = require('path')
const htmlWebpackPlugin = require('html-webpack-plugin')
const miniCssExtractPlugin = require('mini-css-extract-plugin')
const optimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin')
module.exports = {
    mode: 'production',                 //生產:development,開發:production
    /* 
    1、entry:
        1、單入口,字符串表示-----打包一個chunk,生成一個build
            entry:'./src/index.js',
        2、多入口,數組------打包成一個chunk,生成一個build
            entry:['./src/index.js','./src/cc.js'],
        3、對象的寫法  -----有幾個文件生成幾個chunk,生成幾個build
            entry:{
                one:'./src/one.js',
                two:'./src/two.js'
            }
    */
    entry: './src/index.js',
    output: {
        filename: '[name].js',
        // **對象多入口寫法entry: filename:'[name].js',
        path: path.resolve(__dirname, 'dist'),
    },
    // loader  處理非js資源   如html,css,img
    module: {
        rules: [
            /* 
                一個用    loader:css-loader
                一個以上  use:[]
                從右往左
                 {
                    test: /\.css$/,
                    use: [
                        'style-loader',
                        'css-loader']
                },
            */

            {
                test: /\.css$/,
                use: [
                    miniCssExtractPlugin.loader,
                    'css-loader',
                    'postcss-loader'
                ]
            },
            {
                test: /\.less$/,
                use: [
                    'style-loader',
                    'css-loader',
                    'less-loader'
                ]
            },
            {
                test: /\.sass$/,
                use: [
                    'style-loader',
                    'css-loader',
                    'sass-loader'
                ]
            },
            {
                test: /\.(png|jpg|jpeg)$/,
                loader: 'url-loader',
                options: {
                    publicPath:'./images/',
                    outputPath: 'imgs/',
                    name:'[name][hasg].[ext]',//命名hash+名稱
                    limit:1024*8,//限制8k一下轉base64
                }
            },
            {
                test: /\.(html)$/,
                loader: 'html-loader',
            },
            {
                // exclude 排查資源
                exclude:/\.(js|json|html|css|less|scss|png|jpg)$/,
                loader:'file-loader',
                options:{
                    outputPath: 'font/', //大包位置
                    publicPath:'./font', //尋找位置
                    name:'[name][hasg].[ext]',//命名hash+名稱
                   
                }
            },
            // eslint 只檢查js
            {
                test: /\.js$/,
               //只檢查自己寫的代碼,不檢查第三方的
               exclude:/node_modules/,
               loader:'eslint-loader',
               options:{
                   fix:true,//自動修復
               }
            },
        ]
    },
    // plugin插件,執行范圍更廣的任務  打包到開發壓縮
    plugins: [
        // 打包壓縮html(打包多個就實例化new多個)
        new htmlWebpackPlugin({
            template: './src/index.html', //打包的文件
            filename: 'demo.html',     //打包后的名稱
            chunks: [],               //指定使用的js文件
            minify: {                  //壓縮
                // 移除空格
                collapseWhitespace: true,
                // 移除注釋
                removeComments: true,
            }
        }),
        new miniCssExtractPlugin({ filename: 'demo.css' }),
        new optimizeCssAssetsWebpackPlugin()
    ],
    // 在webpack5 需要加上這個選項才會自動刷新頁面
    target:"web",

    devServer:{
        port:3001,
        compress:true,//自動更新
        open:true,//自動打開瀏覽器
        hot:true//HMR模塊熱替換
    }
}

postcss.config.js

module.exports={
    plugins:[
     require('postcss-preset-env')()   
    ]
}

相關依賴文件

package.json

{
  "name": "webpack5s",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev":"webpack serve --mode development --port 3000",
    "build":"webpack --mode production"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "css-loader": "^6.2.0",
    "eslint": "^7.31.0",
    "eslint-config-airbnb-base": "^14.2.1",
    "eslint-loader": "^4.0.2",
    "eslint-plugin-import": "^2.23.4",
    "file-loader": "^6.2.0",
    "html-loader": "^2.1.2",
    "html-webpack-plugin": "^5.3.2",
    "less": "^4.1.1",
    "less-loader": "^10.0.1",
    "mini-css-extract-plugin": "^2.1.0",
    "optimize-css-assets-webpack-plugin": "^6.0.1",
    "post-loader": "^2.0.0",
    "postcss-loader": "^6.1.1",
    "postcss-preset-env": "^6.7.0",
    "style-loader": "^3.2.1",
    "url-loader": "^4.1.1",
    "webpack": "^5.46.0",
    "webpack-cli": "^4.7.2",
    "webpack-dev-server": "^3.11.2"
  },
  "browserslist": [
    ">0.2%",
    "last 2 version",
    "not dead"
  ],
  "eslintConfig": {
    "extends": "airbnb-base"
  }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM