一、Webpack基本配置及使用

一、Webpack基本配置及使用

1、安裝本地Webpack

webapck webpack-cli -D
// -D 表示上線不需要打這個包

// 初始化一下,記錄安裝的依賴
yarn init -y

// 5.2支持的npx語法可以直接執(zhí)行webpack
// 默認(rèn)去找node_modules下面的bin文件里面的webpack.cmd
npx webpack

2、 Webpack可以0配置

打包工具 -> 輸出后的結(jié)果(js模塊)

打包 -> 支持js模塊化

// 執(zhí)行這行命令,即可打包出一個main.js文件
npx webpack

提示需要配置mode

3、手動配置Webpack

1. 簡單示例

默認(rèn)配置文件的名字:webpack.config.js

// webpack 是 node 寫出來的 所以要用node的寫法來運行
const path = require('path');
// 這是一個導(dǎo)出的配置文件
module.exports = {
  mode: 'development', // 模式(兩種):production development
  entry: './src/index.js', // 入口
  output: { // 出口
    filename: 'bundle.js', // 打包后的文件名
    path: path.resolve(__dirname, 'dist') // 路徑(必須是一個絕對路徑),__dirname不加也可以
  }
}

// 結(jié)果:會在根目錄下有一個 dist/bundle.js 文件
// 可以在瀏覽器環(huán)境中運行即可

簡易示例文件

// src/index.js
let str = require('./a.js');
console.log(str);

// src/a.js
module.exports = 'hello';

打包后的結(jié)果

// dist/bundle.js
(() => {
  var __webpack_modules__ = {
    "./src/a.js": // key -> 模塊的路徑
    (module) => { // value -> 函數(shù)
      eval(
        "module.exports = 'hello'\n\n//# sourceURL=webpack://practise/./src/a.js?"
      );
    },

    "./src/index.js":
    (
      __unused_webpack_module,
      __unused_webpack_exports,
      __webpack_require__
    ) => {
      eval(
        'let str = __webpack_require__("./src/a.js")\r\n\r\nconsole.log(str)\n\n//# sourceURL=webpack://practise/./src/index.js?'
      );
    },
  };
  // 定義了一個緩存[如果模塊加載完了,不需要再次加載,從緩存中取出即可]
  var __webpack_module_cache__ = {};
  // 配置實現(xiàn)require方法(因為require無法在瀏覽器中運行)
  function __webpack_require__(moduleId) {
    var cachedModule = __webpack_module_cache__[moduleId];
    // 檢查模塊在不在緩存中,如果在緩存中,直接返回模塊
    if (cachedModule !== undefined) {
      return cachedModule.exports;
    }
    // 安裝一個模塊[key: Object]
    var module = (__webpack_module_cache__[moduleId] = {
      exports: {},
    });
    // 通過key找到對應(yīng)函數(shù)并執(zhí)行
    __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
    // 返回對應(yīng)的module.exports即可
    return module.exports;
  }
  var __webpack_exports__ = __webpack_require__("./src/index.js"); // './src/index.js': 入口模塊
})();

2. 修改配置文件名

如果想要將配置文件名修改,如:webpack.config.my.js ,此時打包拋出異常

image.png

但是我們希望可以找到我們的配置文件。可以這樣做:

npx webpack --config webpack.config.my.js

但是為了更方便,我們可以在 package.json 中進行配置:

{
    //...
    "scripts": {
        "build": "webpack --config webpack.config.my.js"
     }
    //...
}

執(zhí)行 npm run buildyarn build 即可,其他類似。

但是下面這樣寫是需要注意的:

"scripts": {
    "build": "webpack"
}

// 它并不是一個參數(shù),不會識別config后面的內(nèi)容
npm run build --config webpack.config.my.js
yarn build --config webpack.config.my.js // yarn命令是可以的

// 如果一定要這樣寫,可以使用下面這種方式
npm run build -- --config webpack.config.my.js

3. 本地開發(fā)服務(wù)(通過ip訪問)[webpack-dev-server]

webpack-dev-server

// 可通過 npx webpack-dev-server 開啟,也可配置腳本

// package.json
"scripts": {
    "dev": "webpack-dev-server"
}

// webpack.config.js
module.exports = {
    // ...
    devServer: { // 開發(fā)服務(wù)器的配置
        port: 3000, // 端口號配置
        progress: true, // 可以看到打包進度條
        contentBase: './dist', // 指向打包目錄,希望以這個目錄作為靜態(tài)服務(wù)
        compress: true // 啟動gzip壓縮
    }
    // ...
}

由于高版本的 webpack 與 webpack-dev-server 的兼容問題,如果不成功,可以修改腳本如下:

// package.json
"scripts": {
    "dev": "webpack serve"
}

4. 使用模板自動插入腳本[html-webpack-plugin]

html-webpack-plugin

// webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin'); // 這是一個類

module.exports = {
    // ...
    output: { // 出口
        filename: 'bundle.[hash].js', // 打包后的文件名,這里也加個hash避免緩存
        // filename: 'bundle.[hash:8].js', // 打包后的文件名,這里也加個hash避免緩存:hash只要8位
        path: path.resolve(__dirname, 'dist') // 路徑(必須是一個絕對路徑),__dirname不加也可以
    },
    plugins: [ // 數(shù)組:放著所有的webpack插件
        new HtmlWebpackPlugin({
            template: './src/index.html', // 模板
            filename: 'index.html', // 打包后的文件名
            minify: {
                removeAttributeQuotes: true, // 刪除屬性雙引號
                collapseWhitespace: true // 折疊空行,變成一行
            },
            hash: true // 避免緩存問題,加上hash戳
        })
    ]
    // ...
}

5. 樣式處理

Webpack默認(rèn)只支持 JS 模塊,所以對于 CSS ,需要特殊處理。

yarn add css-loader style-loader -D

yarn add less less-loader -D

...

// webpack.config.js
module.exports = {
    // ...
    module: { // 模塊
        rules: [ // 規(guī)則
            {
                // css-loader: 解析 @import 這種語法的
                // style-loader: 把css插入到head的標(biāo)簽中
                // loader特點:希望單一
                // loader的用法:字符串只用一個loader
                // 多個loader需要數(shù)組
                // loader的順序:默認(rèn)從右向左、從下到上執(zhí)行
                // loader還可以寫成對象的形式
                test: /\.css$/,
                use: [
                    {
                        loader: 'style-loader',
                        options: {
                            // insertAt: 'top' // css的樣式插入到頂部,避免head中的style被覆蓋
                            // insertAt 已廢棄
                            insert: () => {

                            }
                        }
                    },
                    'css-loader'
                ]
            },
            {
                // 處理less文件
                // 還有 sass stylus, 類似的處理方式
                // sass -> node-sass sass-loader
                // stylus -> stylus-loader
                test: /\.less$/,
                use: [
                    {
                        loader: 'style-loader',
                        options: {
                            // insertAt: 'top' // css的樣式插入到頂部,避免head中的style被覆蓋
                            // insertAt 已廢棄
                            insert: () => {

                            }
                        }
                    },
                    'css-loader', // 解析 @import 這種語法的
                    'less-loader' // less -> css
                ]
            }
        ]
    }
    // ...
}

1. CSS抽離成單獨的文件

mini-css-extract-plugin

yarn add mini-css-extract-plugin -D

// webpack.config.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
    plugins: [ // 數(shù)組:放著所有的webpack插件
        new MiniCssExtractPlugin({
            filename: 'main.css' // 抽離css的文件名
        })
    ],
    module: { // 模塊
        rules: [ // 規(guī)則
            {
                test: /\.css$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    'css-loader'
                ]
            },
            {
                test: /\.less$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    'css-loader', // 解析 @import 這種語法的
                    'less-loader' // less -> css
                ]
            }
        ]
    }
}

2. 自動添加瀏覽器前綴

yarn add postcss-loader autoprefixer -D

配置如下:

// webpack.config.js
module.exports = {
    module: {
        rules: [
            {
                test: /\.css$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    'css-loader',
                    'postcss-loader'
                ]
            },
            {
                test: /\.less$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    'css-loader',
                    'postcss-loader',
                    'less-loader'
                ]
            }
        ]
    }
}

但是我們要告訴webpack我們要使用 autoprefixer, 所以需要在根目錄(webpack.config.js 同級目錄)新建一個 postcss.config.js 文件:

// postcss.config.js
module.exports = {
    plugins: [
        require('autoprefixer')
    ]
}

如果以上未生效,在 package.json 文件中增加如下配置:

// package.json
{
    // ...
    "browserslist": [
        "last 2 versions",
        "> 1%",
        "iOS 7",
        "last 3 iOS versions"
    ]
    // ...
}

3. CSS 壓縮

optimize-css-assets-webpack-plugin

配置如下:

// webpack.config.js
module.exports = {
    // ...
    optimization: { // 優(yōu)化項
        minimizer: [
            new OptimizeCssAssetsWebpackPlugin()
        ]
    }
    // ...
}

但是,使用了這個插件,會導(dǎo)致 js 不會被壓縮了,所以必須配合使用另外一個插件:

uglifyjs-webpack-plugin

// webpack.config.js
const UglifyjsWebpackPlugin = require('uglifyjs-webpack-plugin')

module.exports = {
    // ...
    optimization: { // 優(yōu)化項
        minimizer: [
            new UglifyjsWebpackPlugin({
                cache: true, // 是否使用緩存
                parallel: true, // 是否是并發(fā)打包,可以同時打多個
                sourceMap: true // 壓縮完js,ES6變?yōu)镋S6,需要一個源碼映射
            }),
            new OptimizeCssAssetsWebpackPlugin()
        ]
    },
    // ...
}

6. 轉(zhuǎn)換ES6語法

Babel

1. 基礎(chǔ)語法

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

// webpack.config.js
module.exports = {
    // ...
    module: {
        rules: [
            {
                test: /\.js$/,
                use: {
                    loader: 'babel-loader', // 用babel-loader需要把es6轉(zhuǎn)換為es5
                    options: {
                        presets: [
                            '@babel/preset-env' // 把es6轉(zhuǎn)換為es5的模塊
                        ]
                    }
                }
            }
        ]
    }
    // ...
}

2. class

yarn add @babel/plugin-proposal-class-properties -D

// webpack.config.js
module.exports = {
    // ...
    module: {
        rules: [
            {
                test: /\.js$/,
                use: {
                    loader: 'babel-loader', // 用babel-loader需要把es6轉(zhuǎn)換為es5
                    options: {
                        presets: [
                            '@babel/preset-env' // 把es6轉(zhuǎn)換為es5的模塊
                        ],
                        plugins: [
                            '@babel/plugin-proposal-class-properties'
                        ]
                    }
                }
            }
        ]
    }
    // ...
}

3. 裝飾器

yarn add @babel/plugin-proposal-decorators -D

// webpack.config.js
module.exports = {
    // ...
    module: {
        rules: [
            {
                test: /\.js$/,
                use: {
                    loader: 'babel-loader', // 用babel-loader需要把es6轉(zhuǎn)換為es5
                    options: {
                        presets: [
                            '@babel/preset-env' // 把es6轉(zhuǎn)換為es5的模塊
                        ],
                        plugins: [
                            ["@babel/plugin-proposal-decorators", { "legacy": true }],
                            ["@babel/plugin-proposal-class-properties", { "loose" : true }]
                        ]
                    }
                }
            }
        ]
    }
    // ...
}

4. JS語法及校驗

代碼運行時的一個包。

1. generator、promise 等的處理

yarn add @babel/plugin-transform-runtime -D

yarn add @babel/runtime

// webpack.config.js
module.exports = {
    // ...
    module: {
        rules: [
            {
                test: /\.js$/,
                use: {
                    loader: 'babel-loader', // 用babel-loader需要把es6轉(zhuǎn)換為es5
                    options: {
                        presets: [
                            '@babel/preset-env' // 把es6轉(zhuǎn)換為es5的模塊
                        ],
                        plugins: [
                            ["@babel/plugin-proposal-decorators", { "legacy": true }],
                            ["@babel/plugin-proposal-class-properties", { "loose" : true }],
                            "@babel/plugin-transform-runtime"
                        ]
                    }
                },
                include: path.resolve(__dirname, 'src'), // 包括,只要這個目錄下的
                exclude: /node_modules/ // 排除這個目錄下面的
            }
        ]
    }
    // ...
}
2. 實例方法不會被解析的處理

如 includes。

yarn add @babel/polyfill

3. JS語法校驗

ESLint

yarn add eslint eslint-loader -D

// webpack.config.js
module.exports = {
    // ...
    module: {
        rules: [
            {
                test: /\.js$/, // 可以同時寫多個
                use: {
                    loader: 'eslint-loader',
                    options: {
                        enforce: 'pre' // previous 強制在其他的loader之前執(zhí)行   
                    }
                }
            },
            {
                test: /\.js$/,
                // ...
            }
        ]
    }
    // ...
}

7. 全局變量的引入(三種方式)

1. expose-loader

2. ProvidePlugin

3. 引入不打包(externals)

expose-loader

暴露全局的loader 內(nèi)聯(lián)的loader

yarn add expose-loader

用法:

// 1、 內(nèi)聯(lián)的方式
import $ from 'expose-loader?$!jquery'
console.log(window.$)


// 2、配置到webpack.config.js中的方式,并且引入使用
import $ from 'jquery'
// ----
module.exports = {
    // ...
    module: {
        rules: [
            {
                test: require.resolve('jquery'),
                use: 'expose-loader?$'
            }
        ]
    }
    // ...
}

// 3、配置到webpack.config.js中的方式
// webpack.config.js
const webpack = require('webpack');
module.exports = {
    // ...
    plugins: [
        new webpack.ProvidePlugin({ // 在每個模塊中都注入 $。 [但是這樣 window.$ 拿不到]
            $: 'jquery'
        })
    ]
    // ...
}

注意

externals

// webpack.config.js
const webpack = require('webpack');
module.exports = {
    // ...
    externals: { // 意義:這個模塊是外部引入的,不需要打包
        jquery: '$'
    }
    // ...
}

8. 圖片處理

1. 在JS中創(chuàng)建圖片引入(new Image())

yarn add file-loader -D

file-loader 默認(rèn)會在內(nèi)部生成一張圖片到打包后的目錄下,把生成的圖片的名字返回回來

// webpack.config.js
module.exports = {
    // ...
    module: {
        rules: [
            {
                test: /\.(jpg|png|gif|jpeg)$/,
                use: 'file-loader'
            }
        ]
    }
    // ...
}

2. 在CSS中引入(background('url'))

css-loader 已支持

3. 在html中引入(<img src="">

yarn add html-withimg-loader -D

// webpack.config.js
module.exports = {
    // ...
    module: {
        rules: [
            {
                test: /\.html$/,
                use: 'html-withimg-loader'
            }
        ]
    }
    // ...
}

4. base64轉(zhuǎn)換圖片

當(dāng)圖片大于某個限制大小時,使用file-loader產(chǎn)出一個文件。但是小于這個限制值的時候,可以用base64來轉(zhuǎn)化。

可以不用發(fā)起http請求去加載圖片。

yarn add url-loader -D

// webpack.config.js
module.exports = {
    // ...
    module: {
        rules: [
            {
                test: /\.(jpg|png|gif|jpeg)$/,
                use: {
                    loader: 'url-loader',
                    options: {
                        esModule: false,
                        limit: 100 * 1024 // 圖片小于100k,就使用base64,否則用file-loader產(chǎn)生真實的圖片
                    }
                }
            }
        ]
    }
    // ...
}

9. 打包文件分類

1. 圖片目錄

// webpack.config.js
module.exports = {
    // ...
    module: {
        rules: [
            {
                test: /\.(jpg|png|gif|jpeg)$/,
                use: {
                    loader: 'url-loader',
                    options: {
                        esModule: false,
                        limit: 1,
                        outputPath: 'img/' // 打包到打包路徑下的 img 目錄中
                    }
                }
            }
        ]
    }
    // ...
}

但是引用是希望引用域名下這個目錄對應(yīng)的文件:

// webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin'); // 這是一個類

module.exports = {
    // ...
    output: { // 出口
        filename: 'bundle.[hash:8].js',
        path: path.resolve(__dirname, 'dist'),
        publicPath: 'http://127.0.0.1:5500/dist' // 加這樣一個域名
    }
    // ...
}

但是只想給圖片加上這個域名,就可以這樣做:

// webpack.config.js
module.exports = {
    // ...
    output: { // 出口
        filename: 'bundle.[hash:8].js',
        path: path.resolve(__dirname, 'dist')
    }
    // ...
    module: {
        rules: [
            {
                test: /\.(jpg|png|gif|jpeg)$/,
                use: {
                    loader: 'url-loader',
                    options: {
                        esModule: false,
                        limit: 1,
                        outputPath: 'img/',
                        // 加這樣一個域名,并且需要拼接上上面的輸出目錄
                        publicPath: 'http://127.0.0.1:5500/dist/img'
                    }
                }
            }
        ]
    }
    // ...
}

2. 樣式目錄

// webpack.config.js
module.exports = {
    // ...
    plugins: [ // 數(shù)組:放著所有的webpack插件
        new MiniCssExtractPlugin({
            filename: 'css/main.css'
        })
    ]
    // ...
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容