開發(fā)環(huán)境到生產(chǎn)環(huán)境搭建Webpack

第webpack 簡介

webpack 是一種前端資源構(gòu)建工具艺糜,一個靜態(tài)模塊打包器(module bundler)。
webpack 看來, 前端的所有資源文件(js/json/css/img/less/...)都會作為模塊處理滨嘱。它將根據(jù)模塊的依賴關(guān)系進行靜態(tài)分析,打包生成對應(yīng)的靜態(tài)資源(bundle)渣聚。


案例地址: https://github.com/pengjunshan/WebPJS/StudyWebpack

其它Web文章

CSS浮動的使用和解決浮動的五種方法
CSS定位relative愉耙、absolute、fixed使用總結(jié)
原生開發(fā)WebApi知識點總結(jié)
開發(fā)中常用jQuery知識點總結(jié)
C3動畫+H5+Flex布局使用總結(jié)
ES6常用知識總結(jié)
Vue學(xué)習(xí)知識總結(jié)
待續(xù)......

本編文章會講到的知識點

  • webpack初體驗
    • 常用命令
    • HelloWebpack
  • webpack開發(fā)環(huán)境配置
    • 打包html資源
    • 單頁面和多頁面配置
    • 打包css資源
    • 打包圖片資源
    • 打包其它資源
    • devServer自動化
    • 文件歸類配置
  • webpack生產(chǎn)環(huán)境配置
    • 提取css樣式文件
    • css兼容性處理
    • 壓縮css
    • js語法檢查
    • js兼容性處理
    • js和html壓縮
    • 生產(chǎn)環(huán)境配置
  • webpack優(yōu)化環(huán)境配置
    • HMR
    • source-map
    • oneOf
    • 緩存
    • tree shaking
    • code split
    • 懶加載
    • PWA
    • 多進程打包
    • externals
    • dll
    • optimization
  • 常用輔助工具
    • resolve
    • watch監(jiān)控
    • 清除dist文件
    • copy文件到dist
    • BannerPlugin聲明
    • 定義全局變量
    • webpack-merge

webpack初體驗

常用命令

了解yarn和npm命令,至于yarn和npm的區(qū)別我就不多說.

npm yarn 功能
npm i yarn 構(gòu)建項目
npm init -y yarn init -y 初始化項目
npm i vue -s yarn add vue 局部安裝(會打包到代碼中)
npm i vue -d yarn add vue -d 局部安裝(不會打包到代碼中)
npm i vue -g yarn add vue -g 全局安裝依賴包
  • npm i xx -S和yarn add xx

會在package.json的dependencies屬性下添加xx依賴包,生產(chǎn)環(huán)境需要用到的依賴包块饺,比如vue赞辩、jquery項目運行時需要用的庫。

  • npm i xx -D和yarn add xx -D

會在package.json的devDependencies屬性下添加xx依賴包,生產(chǎn)環(huán)境不需要用到的依賴包授艰,比如css-loader辨嗽、less-loader轉(zhuǎn)換css的依賴包。

  • npm i xx -g和yarn add xx -g

安裝模塊到全局淮腾,不會在項目node_modules目錄中保存模塊包糟需。不會將模塊依賴寫入devDependencies或dependencies 節(jié)點。
比如用npm安裝yarn: npm install yarn -g

HelloWebpack

1.新建一個文件夾 初始化項目谷朝,會生成一個package.json文件

yarn init -y
或者npm init -y

2.安裝webpack webpack-cli依賴包

yarn add webpack webpack-cli -D
或者npm i webpack webpack-cli -D

package.json下會生成devDependencies中會有webpack洲押、webpack-cli

{
  "name": "StudyWebpack",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "devDependencies": {
    "webpack": "^4.42.1",
    "webpack-cli": "^3.3.11"
  }
}

3.項目中新建src文件夾,src文件夾下新建index.js
4.項目中新建webpack.config.js文件
5.在webpack.config.js中寫配置項

module.exports = {
    mode:'development',//開發(fā)環(huán)境  development:開發(fā)環(huán)境  production:生成環(huán)境
    entry:'./src/index.js',//入口文件
    output:{//出口配置
        filename:'index.js',//出口文件名
        path:__dirname+'/dist'//出口路徑
    }
}

6.在項目下打開命令行窗口圆凰,運行npx webpack命令杈帐,webpack項目會自動先找到webpack.config配置項,然后根據(jù)配置信息進行打包专钉,成功后項目中會多個dist文件挑童,dist就是打包輸出的結(jié)果。


7.注意:只要修改了webpack.config.js文件就要重新

webpack開發(fā)環(huán)境配置

打包html資源

1.安裝 html-webpack-plugin

yarn add html-webpack-plugin -D
或者npm i html-webpack-plugin -D

2.在webpack.config.js中引入html-webpack-plugin插件并配置使用跃须。詳情看代碼注釋炮沐!


/*
  插件的使用步驟:
  plugins: 1. 下載  2. 引入  3. 使用
*/
//引入html-webpack-plugin
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    //模式
    mode:'development',
    //入口
    entry:'./src/index.js',
    //出口
    output:{
        filename:'bundle.js',//文件名
        path:__dirname+'/dist'//出口路徑
    },
    //配置插件
    plugins:[
        // 功能:默認會創(chuàng)建一個空的HTML,自動引入打包輸出的所有資源(JS/CSS)
        // 需求:需要有結(jié)構(gòu)的HTML文件
        new HtmlWebpackPlugin({
            // 復(fù)制 './src/index.html' 文件回怜,并自動引入打包輸出的所有資源(JS/CSS)
            template:'./src/index.html'
        })
    ]

}

3.運行npx webpack 打包項目大年,dist文件下會生成index.html文件,并且index.html中自動引入了bundle.js文件


單頁面和多頁面配置

entry: 入口起點

  • 方式一:單入口 string -->'./src/index.js'
    打包形成一個chunk玉雾。 輸出一個bundle文件翔试。此時chunk的名稱默認是 main。

  • 多入口 array -->['./src/index.js','./src/add.js']
    所有入口文件最終只會形成一個chunk, 輸出出去只有一個bundle文件复旬。

  • 方式三:多入口 object{index:'./src/index.js', add:'./src/add.js'}
    有幾個入口文件就形成幾個chunk垦缅,輸出幾個bundle文件,此時chunk的名稱是 key。

module.exports = {
    mode: 'development',
    // entry:'./src/index.js',方式一
    // entry:['./src/index.js','./src/add.js'],方式二
    entry: {//方式三
        index: './src/index.js',
        add: './src/add.js',
        home:'./src/home.js'
    },

    //出口
    output: {
        //文件名 [name]根據(jù)入口的名稱定義
        filename: 'js/[name].js',
        //輸出文件目錄(將來所有資源輸出的公共目錄)
        path: __dirname + '/dist',
        // 所有資源引入公共路徑前綴
        publicPath: '/',
        // 非入口chunk的名稱
        chunkFilename: 'js/[name]_chunk.js',
        // library: '[name]', // 整個庫向外暴露的變量名
        // libraryTarget: 'window' // 變量名添加到哪個上 browser
        // libraryTarget: 'global' // 變量名添加到哪個上 node
        // libraryTarget: 'commonjs'
    },
    plugins: [
        //多出口 一般和多入口對應(yīng)
        new HtmlWebpackPlugin({
            template: './src/index.html',
            filename:'index.html',
            //只引入index.js驹碍,不指定的話會引入index壁涎、home.js
            chunks:['index']
        }),
        new HtmlWebpackPlugin({
            template: './src/index.html',
            filename:'home.html',
            chunks:['home']
        }),
    ]
}
打包css資源

1.安裝css-loader style-loader less-loader less,我這里只介紹css和less其它樣式用同樣的配置凡恍。

yarn add css-loader style-loader less-loader less -D

2.配置webpack.config.js,在module中配置css-loader和lessloader怔球。詳情看代碼注釋


//引入插件
const HtmlWbpackPlugin = require('html-webpack-plugin')

module.exports = {
    //模式
    mode:'development',//開發(fā)環(huán)境  development:開發(fā)環(huán)境  production:生成環(huán)境
    //入口
    entry:'./src/index.js',
    //出口
    output:{
        filename:'bundle.js',//出口文件名
        path:__dirname+'/dist'//出口文件路徑
    },
    //插件配置
    plugins:[
        new HtmlWbpackPlugin({
            template:'./src/index.html',//配置一個模板html
            name:'index.html'//生成的html名稱
        })
    ],
    //loader配置
    module:{
        //rules是個數(shù)組嚼酝,因為不同的配置需要不同的loader處理
        rules:[
            {
                //匹配以.css結(jié)尾的文件
                test:/\.css$/,
                // use數(shù)組中l(wèi)oader執(zhí)行順序:從右到左,從下到上 依次執(zhí)行
                use:[
                    // 創(chuàng)建style標簽竟坛,將js中的樣式資源插入進行闽巩,添加到head中生效
                    'style-loader',
                    // 將css文件變成commonjs模塊加載js中,里面內(nèi)容是樣式字符串
                    'css-loader'
                ]
            },
            {
                //匹配以.less結(jié)尾的文件
                test:/\.less$/,
                use:[
                    // 創(chuàng)建style標簽担汤,將js中的樣式資源插入進行涎跨,添加到head中生效
                    'style-loader',
                    // 將css文件變成commonjs模塊加載js中,里面內(nèi)容是樣式字符串
                    'css-loader',
                    // 將less文件編譯成css文件
                    'less-loader'
                ]
            }
        ]
    }
}
打包圖片資源

1.安裝loader,html-loader url-loader file-loader

yarn add file-loader url-loader html-loader -d

2.配置webpack.config崭歧,詳情看代碼注釋隅很。

解決使用html-loader處理html中引入圖片失效,解決方法在url-loader中的options對象中中添加esModule:false屬性率碾。


const HtmlWebpckPlugin = require('html-webpack-plugin')
module.exports = {
    mode:'development',
    entry:'./src/index.js',
    output:{
        filename:'bundle.js',
        path:__dirname+'/dist'
    },
    plugins:[
        new HtmlWebpckPlugin({
            template:'./src/index.html',
            name:'idnex.html'
        })
    ],
    module:{
        rules:[
            {
                test:/\.less$/,
                use:[
                    'style-loader',
                    'css-loader',
                    'less-loader'
                ]
            },
            {
                //匹配圖片結(jié)尾的文件外构,可手動添加
                test:/\.(png|jpg|jpeg|gif)/,
                // 使用url-loader
                loader:'url-loader',
                options:{
                    // 圖片大小小于8kb,就會被base64處理
                    // 優(yōu)點: 減少請求數(shù)量(減輕服務(wù)器壓力)
                    // 缺點:圖片體積會更大(文件請求速度更慢)
                    limit:8*1024,
                     // 問題:因為url-loader默認使用es6模塊化解析播掷,而html-loader引入圖片是commonjs
                    // 解析時會出問題:[object Module]
                    // 解決:關(guān)閉url-loader的es6模塊化审编,使用commonjs解析
                    esModule:false,
                     // 給圖片進行重命名
                    // [hash:10]取圖片的hash的前10位
                    // [ext]取文件原來擴展名
                    name: '[hash:10].[ext]'
                }
            },
            {
                //匹配.html結(jié)尾的文件
                test:/\.html/,
                // 處理html文件的img圖片(負責(zé)引入img,從而能被url-loader進行處理)
                loader:'html-loader'
            }
        ]
    }
}
打包其它資源

1.使用exclude屬性歧匈,排除法
2.配置webpack.config,詳情看代碼注釋


const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
    mode: 'development',
    entry: './src/index.js',
    output: {
        filename: 'bunder.js',
        path: __dirname + '/dist'
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './src/index.html',
            name: 'index.html'
        })
    ],
    module: {
        rules: [
            {
                test: /\.css$/,
                use: ['style-loader', 'css-loader']
            },
            //處理其它資源
            {
                //excude排除法 后期手動添加
                exclude: /\.(css|js|html|less|png|jpg|jpeg|gif)$/,
                //使用file-loader
                loader: 'file-loader',
                options: {
                    name: '[hash:10].[ext]'
                }
            }
        ]
    }
}
devServer自動化

開發(fā)服務(wù)器 devServer后垒酬,只會在內(nèi)存中編譯打包,不會有任何輸出件炉;自動編譯勘究,自動打開瀏覽器,修改代碼后自動刷新瀏覽器斟冕;

1.安裝webpack-dev-server

yarn add webpack-dev-server -D

方法一:配置webpack.config,詳細配置請看代碼注釋


const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
    mode:'development',
    entry:'./src/index.js',
    output:{
        filename:'bundle.js',
        path:__dirname+'/dist'
    },
    plugins:[
        new HtmlWebpackPlugin({
            template:'./src/index.html',
        })
    ],
     // 開發(fā)服務(wù)器 devServer:用來自動化(自動編譯口糕,自動打開瀏覽器,自動刷新瀏覽器~~)
    // 特點:只會在內(nèi)存中編譯打包磕蛇,不會有任何輸出
    // 啟動devServer指令為:npx webpack-dev-server
    devServer: {
        // 項目構(gòu)建后路徑
        contentBase:__dirname+'/dist',
        // 啟動gzip壓縮
        compress: true,
        // 端口號
        port: 3000,
        // 自動打開瀏覽器
        open: true
      }
}

方法二:在wepack.json中配置scripts

{
  "name": "StudyWebpack",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "scripts": {
    "build": "webpack",//打包
    "dev": "webpack-dev-server --open --port 3000 --host"http://開發(fā)服務(wù)器 devServer
  }
文件歸類配置

當(dāng)src下的文件很多時顯得很亂景描,應(yīng)當(dāng)給相應(yīng)的文件歸類;

  • outputPath屬性為loader處理后的文件增加文件夾歸類
  • output輸出對象中 filename:'js/bundle.js'秀撇,增加js文件夾

const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
    // 模式
    mode:'development',
    // 入口
    entry:'./src/js/index.js',
    // 出口
    output:{
        filename:'js/bundle.js',//輸出路徑增加js文件夾
        path:__dirname+'/dist'
    },
    //devServer自動化
    devServer:{
        contentBase:__dirname+'/dist',
        compress:true,
        port:3000,
        open:true
    },
    // 插件配置
    plugins:[
        new HtmlWebpackPlugin({
            template:'./src/index.html'
        })
    ],
    // loader配置
    module:{
        rules:[
            {   // 處理css
                test:/\.css$/,
                use:[
                    'style-loader',
                    'css-loader'
                ]
            },
            {   //處理less
                test:/\.less$/,
                use:[
                    'style-loader',
                    'css-loader',
                    'less-loader'
                ]
            },
            {   //處理圖片
                test:/\.(png|jpg|jpeg|gif)/,
                loader:'url-loader',
                options:{
                    limit: 8*1024,
                    name:'[hash:10].[ext]',
                    exModule:false,
                    outputPath:'imgs'//圖片輸出增加imgs文件夾
                }
            },
            {   //處理html中圖片
                test:/\.html$/,
                loader:'html-loader'
            },
            {   //處理其它文件
                exclude:/\.(css|html|js|less|png|jpg|jpeg|gif)/,
                loader:'file-loader',
                options:{
                    name:'[hash:10].[ext]',
                    outputPath:'media'//其它文件增加輸出文件夾
                }
            }
        ]
    }
}

webpack生產(chǎn)環(huán)境配置

提取css樣式文件

1.安裝mini-css-extract-plugin插件

yarn add mini-css-extract-plugin -D

2.配置webpack.config超棺,詳情看代碼注釋


const HtmlWebpackPlugin = require('html-webpack-plugin')
//1.引入mini-css-extract-plugin
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
    mode:'development',
    entry:'./src/index.js',
    output:{
        filename:'bundle.js',
        path:__dirname+'/dist'
    },
    module:{
        rules:[
            {
                test:/\.css$/,
                use:[
                    // 'style-loader',
                    //3. 這個loader取代style-loader。作用:提取js中的css成單獨文件
                    MiniCssExtractPlugin.loader,
                    'css-loader'
                ]
            },
            {
                test:/\.less$/,
                use:[
                    // 'style-loader',
                    //3. 這個loader取代style-loader呵燕。作用:提取js中的css成單獨文件
                    MiniCssExtractPlugin.loader,
                    'css-loader',
                    'less-loader'
                ]
            }
        ]
    },
    plugins:[
        new HtmlWebpackPlugin({
            template:'./src/index.html'
        }),
        //2.配置插件
        new MiniCssExtractPlugin({
            //對輸出的css文件進行文件夾配置和重命名
            filename:'css/bundle.css'
        })
    ]
}
css兼容性處理

1.安裝postcss-loader postcss-preset-env

yarn add postcss-loader postcss-preset-env -D

2.package.json中配置browserslist

 "browserslist": {
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ],
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ]
  }

3.配置webpack.config棠绘,詳情看代碼注解


const HtmlWebpackPlugin = require('html-webpack-plugin')
//1.引入mini-css-extract-plugin
const MiniCssExtractPlugin = require('mini-css-extract-plugin')

// 設(shè)置nodejs環(huán)境變量 默認是production環(huán)境
// process.env.NODE_ENV = 'development';

module.exports = {
    mode: 'development',
    entry: './src/index.js',
    output: {
        filename: 'bundle.js',
        path: __dirname + '/dist'
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                use: [
                    // 'style-loader',
                    //3. 這個loader取代style-loader。作用:提取js中的css成單獨文件
                    MiniCssExtractPlugin.loader,
                    'css-loader',
                    //幫postcss找到package.json中browserslist里面的配置,通過配置加載指定的css兼容性樣式
                    {
                        // 使用loader的默認配置
                        // 'postcss-loader',
                        // 修改loader的配置
                        loader: 'postcss-loader',
                        options: {
                            ident: 'postcss',
                            plugins: () => [
                                // postcss 的插件
                                require('postcss-preset-env')()
                            ]
                        }
                    }
                ]
            }

        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './src/index.html'
        }),
        //2.配置插件
        new MiniCssExtractPlugin({
            //對輸出的css文件進行文件夾配置和重命名
            filename: 'css/bundle.css'
        })
    ]
}
壓縮css

1.安裝optimize-css-assets-webpack-plugin插件

yarn add optimize-css-assets-webpack-plugin -D

2.配置webpack.config氧苍,詳情看代碼注釋


const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')

//1.引入optimize-css-assets-webpack-plugin
const OptimizeCssAssetsWebapckPlugin = require('optimize-css-assets-webpack-plugin')

module.exports = {
    mode: 'development',
    entry: './src/index.js',
    output: {
        filename: 'bundle.js',
        path: __dirname + '/dist'
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    'css-loader',
                    {
                        loader: 'postcss-loader',
                        options: {
                            ident: 'postcss',
                            plugins: () => [
                                require('postcss-preset-env')()
                            ]
                        }
                    }
                ]
            }

        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './src/index.html'
        }),
        new MiniCssExtractPlugin({
            filename: 'css/bundle.css'
        }),
        //2.配置插件optimize-css-assets-webpack-plugin
        new OptimizeCssAssetsWebapckPlugin()
    ]
}
js語法檢查

1.安裝 eslint,eslint-loader,eslint-config-airbnb-base,eslint-plugin-import

yarn add eslint eslint-loader eslint-config-airbnb-base eslint-plugin-import

2.package.json中配置eslintConfig

"eslintConfig": {
    "extends": "airbnb-base",
    "env": {
      "browser": true
    }
  }

3.配置webapck.config夜矗,詳情解釋看代碼注釋


const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
    mode:'development',
    entry:'./src/index.js',
    output:{
        filename:'bundle.js',
        path:__dirname+'/dist'
    },
    module:{
        rules:[
            {
                // 匹配以.js結(jié)尾的文件
                test:/\.js$/,
                // 排除node_modules下的文件,只檢查自己寫的代碼让虐,不檢查第三方的代碼
                exclude:/node_modules/,
                loader:'eslint-loader',
                options:{
                    //自動修復(fù)eslint錯誤
                    fix:true
                }

            }
        ]
    },
   plugins: [
        new HtmlWebpackPlugin({
            template: './src/index.html'
        })
    ]
}
js兼容性處理

1.安裝babel-loader @babel/core @babel/preset-env core-js

yarn add babel-loader @babel/core @babel/preset-env core-js -D

2.配置webpack.config紊撕,詳情解釋看代碼注釋

module: {
        rules: [
            /*
               js兼容性處理:babel-loader @babel/core 
               1. 基本js兼容性處理 --> @babel/preset-env
                   問題:只能轉(zhuǎn)換基本語法,如promise高級語法不能轉(zhuǎn)換
               2. 全部js兼容性處理 --> @babel/polyfill  
                   問題:我只要解決部分兼容性問題澄干,但是將所有兼容性代碼全部引入,體積太大了~
               3. 需要做兼容性處理的就做:按需加載  --> core-js柠傍,就不需要@babel/polyfill包了
           */
            {
                // 匹配以.js結(jié)尾的文件
                test: /\.js$/,
                // 排除node_modules下的文件麸俘,只檢查自己寫的代碼,不檢查第三方的代碼
                exclude: /node_modules/,
                loader: 'babel-loader',
                options: {
                    // 預(yù)設(shè):指示babel做怎么樣的兼容性處理
                    presets: [
                      [
                        '@babel/preset-env',
                        {
                          // 按需加載
                          useBuiltIns: 'usage',
                          // 指定core-js版本
                          corejs: {
                            version: 3
                          },
                          // 指定兼容性做到哪個版本瀏覽器
                          targets: {
                            chrome: '60',
                            firefox: '60',
                            ie: '9',
                            safari: '10',
                            edge: '17'
                          }
                        }
                      ]
                    ]
                  }
            }
        ]
    }
js和html壓縮

const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
    //生產(chǎn)環(huán)境下js代碼自動壓縮
    mode:'production',
    entry:'./src/index.js',
    output:{
        filename:'bundle.js',
        path:__dirname+'/dist'
    },
    module:{
        rules:[
           
        ]
    },
   plugins: [
        new HtmlWebpackPlugin({
            template: './src/index.html',
            // 壓縮html代碼
            minify: {
                // 移除空格
                collapseWhitespace: true,
                // 移除注釋
                removeComments: true
              }
        })
    ]
}
生產(chǎn)環(huán)境配置

css和less有公共的loader代碼惧笛,可以抽離公共loader代碼从媚,以對象擴展的方式引入;正常來講患整,一個文件只能被一個loader處理拜效,當(dāng)一個文件要被多個loader處理,那么一定要指定loader執(zhí)行的先后順序:先執(zhí)行eslint 在執(zhí)行babel各谚;


const HtmlWebpackPlugin = require('html-webpack-plugin');
// 抽離css插件
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
// 壓縮css插件
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin');
// 復(fù)用loader
const commonCssLoader = [
    MiniCssExtractPlugin.loader,
    'css-loader',
    {
        // 還需要在package.json中定義browserslist
        loader: 'postcss-loader',
        options: {
            ident: 'postcss',
            plugins: () => [require('postcss-preset-env')()]
        }
    }
];
module.exports = {
    mode: 'production',
    entry: './src/index.js',
    output: {
        filename: 'bundle.js',
        path: __dirname + '/dist'
    },
    module: {
        rules: [
            {
                // 處理css
                test: /\.css$/,
                use: [...commonCssLoader]
            },
            {
                //處理less
                test: /\.less$/,
                use: [...commonCssLoader, 'less-loader']
            },
            /*
                正常來講紧憾,一個文件只能被一個loader處理。
                當(dāng)一個文件要被多個loader處理昌渤,那么一定要指定loader執(zhí)行的先后順序:
                    先執(zhí)行eslint 在執(zhí)行babel
            */
            {
                // 在package.json中eslintConfig --> airbnb
                test: /\.js$/,
                exclude: /node_modules/,
                // 優(yōu)先執(zhí)行
                enforce: 'pre',
                loader: 'eslint-loader',
                options: {
                    fix: true
                }
            },
            {
                test: /\.js$/,
                exclude: /node_modules/,
                loader: 'babel-loader',
                options: {
                  presets: [
                    [
                      '@babel/preset-env',
                      {
                        useBuiltIns: 'usage',
                        corejs: {version: 3},
                        targets: {
                          chrome: '60',
                          firefox: '50'
                        }
                      }
                    ]
                  ]
                }
              },
              {
                test: /\.(jpg|png|gif)/,
                loader: 'url-loader',
                options: {
                  limit: 8 * 1024,
                  name: '[hash:10].[ext]',
                  outputPath: 'imgs',
                  esModule: false
                }
              },
              {
                test: /\.html$/,
                loader: 'html-loader'
              },
              {
                exclude: /\.(js|css|less|html|jpg|png|gif)/,
                loader: 'file-loader',
                options: {
                  outputPath: 'media'
                }
              }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './src/index.html',
            minify: {
                collapseWhitespace: true,
                removeComments: true
              }
        }),
        new MiniCssExtractPlugin({
            filename: 'css/bundle.css'
        }),
        new OptimizeCssAssetsWebpackPlugin()
    ]
}

webpack優(yōu)化環(huán)境配置

HMR

作用:一個模塊發(fā)生變化赴穗,只會重新打包這一個模塊(而不是打包所有模塊) 極大提升構(gòu)建速度;
樣式文件:可以使用HMR功能:因為style-loader內(nèi)部實現(xiàn)了;
js文件:默認不能使用HMR功能 --> 需要修改js代碼,添加支持HMR功能的代碼; 注意:HMR功能對js的處理膀息,只能處理非入口js文件的其他文件;
html文件: 默認不能使用HMR功能.同時會導(dǎo)致問題:html文件不能熱更新了~ (不用做HMR功能);解決:修改entry入口般眉,將html文件引入;

devServer: {
      contentBase: __dirname+'/dist',
      compress: true,
      port: 3000,
      open: true,
      // 模塊熱替換
      // hot: true
    }
source-map

source-map: 一種 提供源代碼到構(gòu)建后代碼映射 技術(shù) (如果構(gòu)建后代碼出錯了,通過映射可以追蹤源代碼錯誤)
[inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map

source-map:外部
錯誤代碼準確信息 和 源代碼的錯誤位置
inline-source-map:內(nèi)聯(lián)
只生成一個內(nèi)聯(lián)source-map,錯誤代碼準確信息 和 源代碼的錯誤位置
hidden-source-map:外部
錯誤代碼錯誤原因潜支,但是沒有錯誤位置,不能追蹤源代碼錯誤甸赃,只能提示到構(gòu)建后代碼的錯誤位置
eval-source-map:內(nèi)聯(lián)
每一個文件都生成對應(yīng)的source-map,都在eval, 錯誤代碼準確信息 和 源代碼的錯誤位置
nosources-source-map:外部
錯誤代碼準確信息, 但是沒有任何源代碼信息
cheap-source-map:外部
錯誤代碼準確信息 和 源代碼的錯誤位置 ,只能精確的行
cheap-module-source-map:外部
錯誤代碼準確信息 和 源代碼的錯誤位置 ,module會將loader的source map加入
內(nèi)聯(lián) 和 外部的區(qū)別:

  • 外部生成了文件冗酿,內(nèi)聯(lián)沒有
  • 內(nèi)聯(lián)構(gòu)建速度更快
    開發(fā)環(huán)境:速度快埠对,調(diào)試更友好
    速度快(eval>inline>cheap>...)
    eval-cheap-souce-map
    eval-source-map
    調(diào)試更友好
    souce-map
    cheap-module-souce-map
    cheap-souce-map
    綜合推薦:eval-source-map / eval-cheap-module-souce-map
    生產(chǎn)環(huán)境:源代碼要不要隱藏? 調(diào)試要不要更友好
    內(nèi)聯(lián)會讓代碼體積變大,所以在生產(chǎn)環(huán)境不用內(nèi)聯(lián)
    綜合推薦:source-map / cheap-module-souce-map
// 開發(fā)模式
 mode: 'development',
devtool:'eval-source-map'
//生產(chǎn)模式
 mode: 'production',
devtool:'source-map'
oneOf

在不使用oneOf之前裁替,一個文件被一個loader匹配到后還會繼續(xù)向下匹配其它匹配不了的loader鸠窗,這樣性能不好,使用oneOf后當(dāng)一個文件被一個loader匹配到后就不會向下繼續(xù)匹配了胯究;但是使用oneOf只會匹配一個loader稍计,所以如果設(shè)置了一個文件兩個loader的話需要分開寫,不能寫在同一個oneOf里面裕循。

module: {
    rules: [
      {
        // 在package.json中eslintConfig --> airbnb
        test: /\.js$/,
        exclude: /node_modules/,
        // 優(yōu)先執(zhí)行
        enforce: 'pre',
        loader: 'eslint-loader',
        options: {
          fix: true
        }
      },
      {
        // 以下loader只會匹配一個
        // 注意:不能有兩個配置處理同一種類型文件
        oneOf: [
          {
            // 處理css
            test: /\.css$/,
           // 配置多個loader使用use
            use: [...commonCssLoader]
          },
          {
            //處理less
            test: /\.less$/,
            use: [...commonCssLoader, 'less-loader']
          },
          {
            test: /\.js$/,
                exclude: /node_modules/,
                // 配置單個loader使用loader
                loader: 'babel-loader',
                // 排除node_modules下的js
                exclude: /node_modules/,
                // 只匹配src下的js
                include: __dirname + '/src',
                // 優(yōu)先執(zhí)行
                enforce: 'pre',
                // 延后執(zhí)行
                enforce: 'post',
            options: {
              presets: [
                [
                  '@babel/preset-env',
                  {
                    useBuiltIns: 'usage',
                    corejs: { version: 3 },
                    targets: {
                      chrome: '60',
                      firefox: '50'
                    }
          }
        ]
      }
    ]
  }
緩存

當(dāng)已經(jīng)加載了js或css等其它后臣嚣,再次使用的時候不需要再次進行請求了净刮,而是使用緩存后的文件;

hash: 每次wepack構(gòu)建時會生成一個唯一的hash值硅则。
1.問題: 因為js和css同時使用一個hash值淹父。
2.如果重新打包,會導(dǎo)致所有緩存失效怎虫。(可能我卻只改動一個文件)

chunkhash:根據(jù)chunk生成的hash值暑认。如果打包來源于同一個chunk,那么hash值就一樣大审。
1.問題: js和css的hash值還是一樣的蘸际。
2.因為css是在js中被引入的,所以同屬于一個chunk徒扶。

contenthash:根據(jù)文件的內(nèi)容生成hash值粮彤。不同文件hash值一定不一樣。
1.讓代碼上線運行緩存更好使用

/*
  緩存:
    babel緩存
      cacheDirectory: true
      --> 讓第二次打包構(gòu)建速度更快
*/
{
            test: /\.js$/,
            exclude: /node_modules/,
            loader: 'babel-loader',
            options: {
              presets: [
                  '@babel/preset-env',
              ],
               // 開啟babel緩存
              // 第二次構(gòu)建時姜骡,會讀取之前的緩存
              cacheDirectory:true
            }
          }
tree shaking

tree shaking:去除無用代碼
前提:1. 必須使用ES6模塊化 2. 開啟production環(huán)境
作用: 減少代碼體積

sideEffects配置
"sideEffects": false :所有代碼都都可以進行tree shaking
副作用:可能會把css / @babel/polyfill 文件干掉导坟;
"sideEffects": [".css", ".less"]跳過css、less文件(如果壓過沒有使用css也會打包進去)

code split

[name]:取入口文件的名稱圈澈;

optimization:

  1. 可以將node_modules中代碼單獨打包一個chunk最終輸出
  2. 自動分析多入口chunk中惫周,有沒有公共的文件。如果有會打包成單獨一個chunk
懶加載

當(dāng)一個index.js中引入了其它js文件康栈,進入index.js時不希望立馬加載其它js闯两,用到其它js時再加載;

//當(dāng)點擊按鈕時再加載utils.js文件
document.querySelector('#btn').onclick = function(){
  // 懶加載~:當(dāng)文件需要使用時才加載~
  // 預(yù)加載 prefetch:會在使用之前谅将,提前加載js文件  webpackPrefetch: true
  // 正常加載可以認為是并行加載(同一時間加載多個文件)  
  // 預(yù)加載 prefetch:等其他資源加載完畢漾狼,瀏覽器空閑了,再偷偷加載資源
  // 慎用預(yù)加載饥臂,兼容性問題逊躁,移動端和低版本瀏覽器不支持
  import(/* webpackChunkName: 'test' */'./utils').then(({getName})=>{
    console.log(getName())
  })
}
PWA

1.安裝workbox-webpack-plugin

yarn add workbox-webpack-plugin -D

2.plugins數(shù)組中加載插件

plugins: [
...
  new WorkboxWebpackPlugin.GenerateSW({
    /*
      1. 幫助serviceworker快速啟動
      2. 刪除舊的 serviceworker

      生成一個 serviceworker 配置文件~
    */
    clientsClaim: true,
    skipWaiting: true
  })
  ]
/*
  1. eslint不認識 window、navigator全局變量
    解決:需要修改package.json中eslintConfig配置
      "env": {
        "browser": true // 支持瀏覽器端全局變量
      }
   2. sw代碼必須運行在服務(wù)器上
      --> nodejs
      -->
        npm i serve -g
        serve -s dist 啟動服務(wù)器隅熙,將dist目錄下所有資源作為靜態(tài)資源暴露出去
*/
// 注冊serviceWorker
// 處理兼容性問題
if ('serviceWorker' in navigator) {
  window.addEventListener('load', () => {
    navigator.serviceWorker
      .register('/service-worker.js')
      .then(() => {
        console.log('sw注冊成功了~');
      })
      .catch(() => {
        console.log('sw注冊失敗了~');
      });
  });
}
多進程打包

webpack是單線程模型的稽煤,也就是說Webpack一個時刻只能處理一個任務(wù),不能同時處理多個任務(wù)囚戚。使用thread-loader進行多進程打包酵熙。

1.安裝thread-loader

注意:把這個 thread-loader 放置在其他 loader 之前,options中放一些屬性值驰坊;進程啟動大概為600ms匾二,進程通信也有開銷;只有工作消耗時間比較長,才需要多進程打包;

yarn add thread-loader -D

2.配置js loader

  {
        test: /\.js$/,
        exclude: /node_modules/,
        use: [
          {
            loader:'thread-loader',
            options:{
              workers:2//設(shè)置進程數(shù)量
            }
          },
          {
            loader: 'babel-loader',
            options: {
              presets: [
                '@babel/preset-env',
              ]
            }
          }
        ]
      }
externals

當(dāng)html中引入了cdn第三方庫,js中也Import導(dǎo)入了同個第三方庫技扼,我們就可以使用externals來配置打包;

//html中引入jquery的cdn
<script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>

//js中導(dǎo)入了jquery
import $ from 'jquery'

//webpack.config配置移除jquery打包進去
// 移除某些包被打包進來
    externals:{
        jquery:'jQuery'
    }
dll

使用dll技術(shù)悴务,對某些庫(第三方庫:jquery、react譬猫、vue...)進行單獨打包讯檐,然后再主項目中進行打包時直接引用就可以了,從而加快了打包速度染服。

1.新建webpack.dll.js文件
2.配置webpack.dll.js

const webpack = require('webpack')
module.exports = {
    //需要打包的第三方庫
    entry:{
        jquery:['jquery'],
        // vue:['vue']
    },
    output:{
        filename:'[name].js',
        path:__dirname+'/dll',
        library:'[name]_[hash:10]'// 打包的庫里面向外暴露出去的內(nèi)容叫什么名字
    },
    plugins:[
        // 打包生成一個 manifest.json --> 提供和jquery映射
        new webpack.DllPlugin({
            name:'[name]_[hash:10]',//映射庫暴露出的名稱
            path:__dirname+'/dll/manifest.json'//文件地址
        })
    ],
    mode: 'production'
}

3.配置好webpack.dll.js后運行webpack --config webpack.dll.js命令行别洪,項目下會生成dll文件夾,dll文件夾下會有第三方庫的js和manifest.json文件肌索;
4.安裝add-asset-html-webpack-plugin插件

yarn add add-asset-html-webpack-plugin -D

5.配置webpack.config

const webpack = require('webpack')
const AddAssetHtmlWebpackPlugin = require('add-asset-html-webpack-plugin')
module.exports = {
    mode:'production',//開發(fā)環(huán)境  development:開發(fā)環(huán)境  production:生成環(huán)境
    plugins:[
        // 告訴webpack哪些庫不參與打包蕉拢,同時使用時的名稱也得變~
        new webpack.DllReferencePlugin({
            manifest:__dirname+'/dll/manifest.json'
        }),
        // 將某個文件打包輸出去特碳,并在html中自動引入該資源
        new AddAssetHtmlWebpackPlugin({
            filepath:__dirname+'/dll/jquery.js'
        })
    ],
}
optimization
  • 安裝 terser-webpack-plugin插件
const TerserWebpackPlugin = require('terser-webpack-plugin')
 optimization: {
        splitChunks: {
          chunks: 'all'
          // 默認值诚亚,可以不寫~
          /* minSize: 30 * 1024, // 分割的chunk最小為30kb
          maxSiza: 0, // 最大沒有限制
          minChunks: 1, // 要提取的chunk最少被引用1次
          maxAsyncRequests: 5, // 按需加載時并行加載的文件的最大數(shù)量
          maxInitialRequests: 3, // 入口js文件最大并行請求數(shù)量
          automaticNameDelimiter: '~', // 名稱連接符
          name: true, // 可以使用命名規(guī)則
          cacheGroups: {
            // 分割chunk的組
            // node_modules文件會被打包到 vendors 組的chunk中。--> vendors~xxx.js
            // 滿足上面的公共規(guī)則午乓,如:大小超過30kb站宗,至少被引用一次。
            vendors: {
              test: /[\\/]node_modules[\\/]/,
              // 優(yōu)先級
              priority: -10
            },
            default: {
              // 要提取的chunk最少被引用2次
              minChunks: 2,
              // 優(yōu)先級
              priority: -20,
              // 如果當(dāng)前要打包的模塊益愈,和之前已經(jīng)被提取的模塊是同一個梢灭,就會復(fù)用,而不是重新打包模塊
              reuseExistingChunk: true
            } 
          }*/
        },
        // 將當(dāng)前模塊的記錄其他模塊的hash單獨打包為一個文件 runtime
        // 解決:修改a文件導(dǎo)致b文件的contenthash變化
        runtimeChunk: {
          name: entrypoint => `runtime-${entrypoint.name}`
        },
        minimizer: [
          // 配置生產(chǎn)環(huán)境的壓縮方案:js和css
          new TerserWebpackPlugin({
            // 開啟緩存
            cache: true,
            // 開啟多進程打包
            parallel: true,
            // 啟動source-map
            sourceMap: true
          })
        ]
      }

常用輔助工具

resolve
 resolve: {
        // 配置解析模塊路徑別名: 優(yōu)點簡寫路徑 缺點路徑?jīng)]有提示
        alias: {
            $css: __dirname + '/src/css'
        },
        // 配置省略文件路徑的后綴名只會匹配到一個蒸其, 一般js和css文件名相同敏释,所以不建議匹配css文
        extensions:['.js', '.json', '.jsx', '.css']
    }

    import {addNum} from './add'//省略的后綴
watch監(jiān)控
//自帶功能 不需要安裝
 //監(jiān)控 實時打包
    watch:true,
    //監(jiān)控的配置項
    watchOptions:{
        poll:1000,//每秒詢問1000次
        aggregateTimeout:500,//防抖 停留500毫秒后再打包
        ignored:/node_modules/  //不需要監(jiān)控的文件
    }
清除dist文件
  • 每次打包先清除dist目錄下的文件
  • 安裝clean-webpack-plugin -D
//清除文件
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
 plugins:[
        ...
        new CleanWebpackPlugin()
    ]
copy文件到dist
  • 打包時可以把一些文件夾的內(nèi)容拷貝到dist文件夾
  • 安裝 copy-webpack-plugin -D
//copy文件插件
const CopyWebpackPlugin = require('copy-webpack-plugin')
plugins:[
        ...
        new CopyWebpackPlugin([
            //把doc文件復(fù)制到dist文件夾中
            {from:'./doc',to:'./'}
        ])
      
    ]
BannerPlugin聲明
  • webpack自帶的插件
  • 在打包后的Js文件頭加上注釋聲明
//webpack
const webpack = require('webpack')
 plugins:[
       ...
        new webpack.BannerPlugin('杭州柯林電氣股份有限公司版權(quán)所有')
    ]
定義全局變量
//使用webpack自帶插件DefinePlugin
 new webpack.DefinePlugin({
            DEV:'false',
            FLAGE:JSON.stringify('pjs')//如果想存字符串類型 需要使用JSON.stringify()
        })

if(DEV){
    console.log("正式環(huán)境")
}else{
    console.log("測試環(huán)境")
}
webpack-merge
  • 合并配置文件
  • 分別創(chuàng)建開發(fā)和生產(chǎn)兩個文件
  • 安裝 webpack-merge -D
//webpack.pro.js
let {smart} = require('webpack-merge')
let base = require('./webpack.config.js')
module.exports = smart(base,{
    mode:'production'
})
//webpack.dev.js
let {smart} = require('webpack-merge')
let base = require('./webpack.config.js')
module.exports = smart(base,{
    mode:'development'
})
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市摸袁,隨后出現(xiàn)的幾起案子钥顽,更是在濱河造成了極大的恐慌,老刑警劉巖靠汁,帶你破解...
    沈念sama閱讀 222,252評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蜂大,死亡現(xiàn)場離奇詭異,居然都是意外死亡蝶怔,警方通過查閱死者的電腦和手機奶浦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來踢星,“玉大人澳叉,你說我怎么就攤上這事。” “怎么了耳高?”我有些...
    開封第一講書人閱讀 168,814評論 0 361
  • 文/不壞的土叔 我叫張陵扎瓶,是天一觀的道長。 經(jīng)常有香客問我泌枪,道長概荷,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,869評論 1 299
  • 正文 為了忘掉前任碌燕,我火速辦了婚禮误证,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘修壕。我一直安慰自己愈捅,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 68,888評論 6 398
  • 文/花漫 我一把揭開白布慈鸠。 她就那樣靜靜地躺著蓝谨,像睡著了一般。 火紅的嫁衣襯著肌膚如雪青团。 梳的紋絲不亂的頭發(fā)上譬巫,一...
    開封第一講書人閱讀 52,475評論 1 312
  • 那天,我揣著相機與錄音督笆,去河邊找鬼芦昔。 笑死,一個胖子當(dāng)著我的面吹牛娃肿,可吹牛的內(nèi)容都是我干的咕缎。 我是一名探鬼主播,決...
    沈念sama閱讀 41,010評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼料扰,長吁一口氣:“原來是場噩夢啊……” “哼凭豪!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起晒杈,我...
    開封第一講書人閱讀 39,924評論 0 277
  • 序言:老撾萬榮一對情侶失蹤嫂伞,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后桐智,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體末早,經(jīng)...
    沈念sama閱讀 46,469評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,552評論 3 342
  • 正文 我和宋清朗相戀三年说庭,在試婚紗的時候發(fā)現(xiàn)自己被綠了然磷。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,680評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡刊驴,死狀恐怖姿搜,靈堂內(nèi)的尸體忽然破棺而出寡润,到底是詐尸還是另有隱情,我是刑警寧澤舅柜,帶...
    沈念sama閱讀 36,362評論 5 351
  • 正文 年R本政府宣布梭纹,位于F島的核電站,受9級特大地震影響致份,放射性物質(zhì)發(fā)生泄漏变抽。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,037評論 3 335
  • 文/蒙蒙 一氮块、第九天 我趴在偏房一處隱蔽的房頂上張望绍载。 院中可真熱鬧,春花似錦滔蝉、人聲如沸击儡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽阳谍。三九已至,卻和暖如春螃概,著一層夾襖步出監(jiān)牢的瞬間矫夯,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評論 1 274
  • 我被黑心中介騙來泰國打工谅年, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留茧痒,地道東北人肮韧。 一個月前我還...
    沈念sama閱讀 49,099評論 3 378
  • 正文 我出身青樓融蹂,卻偏偏與公主長得像,于是被迫代替她去往敵國和親弄企。 傳聞我的和親對象是個殘疾皇子超燃,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,691評論 2 361

推薦閱讀更多精彩內(nèi)容

  • 1. 新建一個文件夾,命名為 webpack-cli , webpack-cli 就是你的項目名,項目名建議使用小...
    魯大師666閱讀 1,481評論 1 3
  • 深入淺出Webpack學(xué)習(xí)筆記 基本概念 常用的構(gòu)建工具 所有的構(gòu)建工具所做的工做大致一樣,都是把源代碼翻譯轉(zhuǎn)換成...
    IsaacHHH閱讀 507評論 0 0
  • 初始化項目 進入一個文件夾作為項目的根目錄 npm init 新建src, dist目錄拘领,package.json...
    love_program閱讀 1,244評論 0 4
  • 2018.10.4 天氣:晴 今日休息意乓,偃旗息鼓,明日再戰(zhàn)约素。 面包 届良、餅干 、冰激凌圣猎, 還有……大盤雞士葫、 涼皮 ...
    此處填名字閱讀 109評論 0 0
  • 早上好!#幸福實修#~每天進步1%#幸福實修10班-17柴咪兒--富陽# 20170727(04/30) 【幸福三...
    柴咪兒閱讀 160評論 2 0