webpack介绍

174 阅读3分钟

webpack是一个JavaScript 应用程序的静态模块打包工具

image.png

空文件夹初始化

会生成 package.json文件

npm init -y

安装 webpack webpack-cli

npm install webpack webpack-cli --save-dev

一、入口(entry)

  • 入口起点(entry point)指示 webpack 应该使用哪个模块,来作为构建其内部 依赖图(dependency graph) 的开始。进入入口起点后,webpack 会找出有哪些模块和库是入口起点(直接和间接)依赖的
  • 默认值是 ./src/index.js,但是可以通过在 webpack configuration 中配置 entry 属性,来指定一个(或多个)不同的入口起点

webpack.connfig.js

module.exports = {
    entry: './src/index.js'
}

1. src\index.js

import './index.css'

2. index.css

body{ background-color:green; }

二、输出(output)

  • output 属性告诉 webpack 在哪里输出它所创建的 bundle,以及如何命名这些文件
  • 主要输出文件的默认值是 ./dist/main.js,其他生成文件默认放置在 ./dist 文件夹中。

webpack.config.js

+const path = require('path'); 
module.exports = { 
    entry: './src/index.js', 
+    output: { 
+        path: path.resolve(__dirname, 'dist'), filename: 'main.js'
+    }
};

三、loader(加载器、翻译器)

webpack 只能解析 JavaScript 和 JSON 文件

loader 让 webpack 能够去处理其他类型的文件,并将它们转换为有效模块,以供应用程序使用,以及被添加到依赖图中

loader的执行是 从右向左的,最右侧的loader是读取源文件内容的 最左侧的loader一定会返回一个js模块

1、安装 css-loader style-loader

npm install css-loader style-loader -D

2、webpack.config.js

const path = require('path'); 
module.exports = { 
    mode: 'development', devtool:false, 
    entry: './src/index.js', 
    output: { 
        path: path.resolve(__dirname, 'dist'), 
        filename: 'main.js'
    }, 
+ module: { 
+     rules: [ 
+        { 
            test: /\.css$/, 
            use: ['style-loader','css-loader'] // loader的执行是 从右向左的 最右侧的loader是读取源文件内容的 最左侧的loader一定会返回一个js模块
         } 
+     ] 
+ } 
};

四、插件(plugin)

loader 用于转换某些类型的模块,而插件则可以用于执行范围更广的任务。包括:打包优化,资源管理,注入环境变量

模版:src\index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    
</body>
</html>

安装插件HtmlWebpackPlugin

HtmlWebpackPlugin 根据模版index.html 自动引入打包后的 main.js文件

npm i html-webpack-plugin -D

webpack.config.js

const path = require('path'); 
+const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = { 
    mode: 'development', devtool:false, 
    entry: './src/index.js', 
    output: { 
        path: path.resolve(__dirname, 'dist'), 
        filename: 'main.js'
    }, 
    module: { 
        rules: [ 
            { 
                test: /\.css$/, 
                use: ['style-loader','css-loader'] // loader的执行是 从右向左的 最右侧的loader是读取源文件内容的 最左侧的loader一定会返回一个js模块
             } 
        ]
    }, 
+   plugins: [ 
+       new HtmlWebpackPlugin({template: './src/index.html'}) 
+   ]
};

打包结果

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
+   <script defer src="main.js"></script></head>
<body>
    
</body>
</html>

五、模式(mode)

webpack 4.x 版本引入了 mode 的概念

1 环境差异

  • 开发环境

    • 需要生成 sourcemap 文件
    • 需要打印 debug 信息
    • 需要 live reload 或者 hot reload 的功能
  • 生产环境

    • 可能需要分离 CSS 成单独的文件,以便多个页面共享同一个 CSS 文件
    • 需要压缩 HTML/CSS/JS 代码
    • 需要压缩图片
  • 其默认值为 production

在不配置的情况下 console.log(process.env.NODE_ENV) 会被编译为console.log("production")

2、 如何区分环境

--mode用来设置模块内的process.env.NODE_ENV

cross-env用来设置node环境的process.env.NODE_ENV

DefinePlugin用来设置模块内的全局变量

2.1 mode配置
//webpack.config.js
module.exports = {
  mode: 'development'
}
2.2 命令行配置

只能影响模块内,无法在webpack配置文件中获取此变量

//webpack.config.js
"scripts": { 
    "build": "webpack --mode=production", 
    "dev": "webpack --mode=development" 
},
index.js 打印结果
console.log(process.env.NODE_ENV);// development | production
webpack.config.js 打印结果
console.log('NODE_ENV',process.env.NODE_ENV);// undefined
2.3 命令行配置
  • webpack的mode默认为production
  • webpack serve的mode默认为development
  • 可以在模块内通过process.env.NODE_ENV获取当前的环境变量,无法在webpack配置文件中获取此变量
// package.json
"scripts": { 
    "build": "webpack", 
    "dev": "webpack serve" 
},
index.js 打印结果
console.log(process.env.NODE_ENV);// development | production
webpack.config.js 打印结果
console.log('NODE_ENV',process.env.NODE_ENV);// undefined
2.4 DefinePlugin插件

可以在编译时 替换源码中的字符串 不限于process.env.NODE_ENV

  • 可以在任意模块内通过 process.env.NODE_ENV 获取当前的环境变量
  • 但无法在node环境(webpack 配置文件中)下获取当前的环境变量
  • 键和值可以是任意字符串 只能是字符串
  • 只是找到源码中存在“键”的地方都替换成“值”对应的字符串,和window无关
//webpack.config.js
plugins: [
    new HtmlWebpackPlugin({ template: './src/index.html' }),
    new webpack.DefinePlugin({
        'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
    })
]
index.js 打印结果
console.log(process.env.NODE_ENV);// development | production
webpack.config.js 打印结果
console.log('NODE_ENV',process.env.NODE_ENV);// undefined
console.log('NODE_ENV',NODE_ENV);// error !!!
2.5 cross-env
  • 只能设置node环境下的变量NODE_ENV
安装 cross-env
npm i cross-env -D
package.json 设置
"scripts": {
  "build": "cross-env NODE_ENV=development webpack"
}
webpack.config.js 打印结果 及使用
const webpack = require('webpack');
console.log('process.env.NODE_ENV',process.env.NODE_ENV);// development
module.exports = {
    mode: process.env.NODE_ENV,
    //...
    plugins: [
        //...
        new webpack.DefinePlugin({
            'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
        })
    ]
}

3、 配置区分环境的步骤

3.1 安装cross-env
npm i cross-env -D
3.2 package.json 设置
"build": "cross-env NODE_ENV=development webpack"
3.3 webpack.config.js设置
const webpack = require('webpack');
module.exports = {
    mode: process.env.NODE_ENV,
    //...
    plugins: [
        //...
        new webpack.DefinePlugin({
            'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
        })
    ]
}

Q&A、webpack 和 webpack-cli 的区别

webpack 是打包的核心包

webpack-cli是命令行工具包