前言

作为前端开发者,相信大家或多或少都接触过webpack,现如今webpack已经渗透在了前端的各个方面,所以我们有必要来了解并学习webpackwebpack 是一种用于构建 JavaScript 应用程序的静态模块打包器,它能够以一种相对一致且开放的处理方式,加载应用中的所有资源文件(图片、CSS、视频、字体文件等),并将其合并打包成浏览器兼容的 Web 资源文件。webpack相比其它构建工具功能更加强大,可扩展性也更强,它能够融合多种工程化工具,将开发阶段的应用代码编译、打包成适合网络分发、客户端运行的应用产物。

核心概念

输入输出

entry

webpack的构建入口,入口起点(entry point) 指示 webpack 应该使用哪个模块,来作为构建其内部 依赖图(dependency graph) 的开始。进入入口起点后,webpack 会找出有哪些模块和库是入口起点(直接和间接)依赖的。

// 单入口
module.exports = {
 entry: './src/main.js'
}

// 多入口
module.exports = {
 entry: {
   a: './src/a.js',
   b: './src/b.js'
}
}

output

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

// 单入口
module.exports = {
 entry: './src/main.js',
 output: {
   filename: 'bundle.js',  
   path: path.resolve(__dirname, 'dist'),
}
}
// 多入口
module.exports = {
 entry: {
   a: './src/a.js',
   b: './src/b.js'
},
 output: {
   filename: '[name].[hash:6].js', // 通过占位符确保文件名唯一,考虑缓存问题,还可以为文件名加上hash
   path: __dirname + '/dist',
   publicPath: '/',    // 生产环境一般是CDN地址,开发环境配置为/或不配置
}
}

模块处理

loader

webpack 只能理解 JavaScript 和 JSON 文件,这是 webpack 开箱可用的自带能力。loader 让 webpack 能够去处理其他类型的文件,并将它们转换为有效 模块,以供应用程序使用,以及被添加到依赖图中。

比如:配置webpack为css文件应用css-loader

module.exports = {
 module: {
   rules: [
    {test: /.css$/, use: 'css-loader'}
  ]
}
}

module.rules 允许你在 webpack 配置中指定多个 loader。 这种方式是展示 loader 的一种简明方式,并且有助于使代码变得简洁和易于维护。

plugin

插件 是 webpack 的 支柱 功能。Webpack 自身也是构建于你在 webpack 配置中用到的 相同的插件系统 之上!

插件目的在于解决 loader 无法实现的其他事。Webpack 提供很多开箱即用的 插件

比如:为编译过程添加进度报告插件

const Webpack = require('webpack')
module.exports = {
 plugins: [new Webpack.ProgressPlugin()]
}

resolve

用于配置模块路径解析规则,可用于帮助 Webpack 更精确、高效地找到指定模块

比如配置别名:

创建 importrequire 的别名,来确保模块引入变得更简单。例如,一些位于 src/ 文件夹下的常用模块:

module.exports = {
 resolve: {
   alias: {
     node_modules: path.resolve(__dirname, './node_modules'),
     '@': path.resolve(__dirname, './src'),
     api: path.resolve(__dirname, './src/api'),
     components: path.join(__dirname, './src/components'),
  }
}
}

module

这些选项决定了如何处理项目中的不同类型的模块

比如我们常见的loader就是在module.rules内配置的。

module.exports = {
 module: {
   rules: [
    {test: /.css$/, use: 'css-loader'}
  ]
}
}

externals

用于声明外部资源,Webpack 会直接忽略这部分资源,跳过这些资源的解析、打包操作

比如防止将某些 import 的包(package)打包到 bundle 中,而是在运行时(runtime)再去从外部获取这些扩展依赖(external dependencies)

比如:从CDN引入Vue

<!-- index.html -->
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.3/vue.min.js"></script>
// webpack.config.js
module.exports = {
 externals: {
   vue: 'vue'
}
}

后处理

optimization

用于控制如何优化产物包体积,内置 Dead Code Elimination、Scope Hoisting、代码混淆、代码压缩等功能

从 webpack 4 开始,会根据你选择的 mode 来执行不同的优化, 不过所有的优化还是可以手动配置和重写。

module.exports = {
//...
optimization: {
chunkIds: 'named',
},
};

target

用于配置编译产物的目标运行环境,支持 web、node、electron 等值,不同值最终产物会有所差异

比如:target设置为node,webpack将在node环境下进行编译

module.exports = {
target: 'node'
}

mode

提供 mode 配置选项,告知 webpack 使用相应模式的内置优化。

string = 'production': 'none' | 'development' | 'production'
module.exports = {
mode: 'development',
};

或者从cli--mode 参数进行传递

webpack --mode development

开发效率

watch

启用 Watch 模式。这意味着在初始构建之后,webpack 将继续监听任何已解析文件的更改。

module.exports = {
watch: true
}

️注意:webpack-dev-serverwebpack-dev-middleware默认是开启watch模式的

devtool

此选项控制是否生成,以及如何生成 source map。

string = 'eval' | false

选择一种 source map 风格来增强调试过程。不同的值会明显影响到构建(build)和重新构建(rebuild)的速度。

devServer

用于配置与 HMR 强相关的开发服务器功能

通过 webpack-dev-server 的这些配置,能够以多种方式改变其行为,这里比较常见的配置有:porthostproxy

module.exports = {
devServer: {
static: {
directory: path.join(__dirname, 'public'),
},
compress: true,
port: 9000,
}
}

cache

Webpack 5 之后,该项用于控制如何缓存编译过程信息与编译结果

缓存生成的 webpack 模块和 chunk,来改善构建速度。cache 会在开发 模式被设置成 type: 'memory' 而且在 生产 模式 中被禁用。 cache: truecache: { type: 'memory' } 配置作用一致。 传入 false 会禁用缓存:

module.exports = {
cache: false
}

上手配置

了解完上面这些webpack核心概念,我们可以尝试来手动配置好一个Vue开发环境

初始化项目

首先npm init -y初始化package.json文件

接着安装好我们的webpackwebpack-cli

npm i webpack webpack-cli -D

️注意: 我这里的webpack是5版本的

"webpack": "^5.85.1",
"webpack-cli": "^4.7.2",

处理Vue代码

原生 Webpack 并不能处理这种内容格式的文件,为此我们需要引入专用于 Vue SFC 的加载器:vue-loader

npm i vue-loader
// webpack.config.js

const Webpack = require('webpack')
const {VueLoaderPlugin} = require('vue-loader')
module.exports = {
entry: './src/main.js',
output: {
filename: 'bundle.[hash:6].js',
path: __dirname + '/dist',
},
module: {
rules:[
{test: /.vue$/, use: 'vue-loader'},
]
},
plugins:[
new Webpack.ProgressPlugin(),
new VueLoaderPlugin(),
],
}

提示:vue-loader 库同时提供用于处理 SFC 代码转译的 Loader 组件,与用于处理上下文兼容性的 Plugin 组件,两者需要同时配置才能正常运行。

此时我们的文件结构是这样的,大致与Vue项目结构一致

尝试启动看一下:

// package.json
"dev": "webpack --mode development",
npm run dev

由于我们的vue文件中有css内容,而webpack默认是不理解css内容的,所以导致报错了

处理CSS内容

这里需要安装style-loadercss-loader来进行处理。

修改webpack配置

// webpack.config.js
const Webpack = require('webpack')
const {VueLoaderPlugin} = require('vue-loader')
module.exports = {
entry: './src/main.js',
output: {
filename: 'bundle.[hash:6].js',
path: __dirname + '/dist',
},
module: {
rules:[
{test: /.vue$/, use: 'vue-loader'},
{
test: /.css$/,
use: ['style-loader', 'css-loader']
}
]
},
plugins:[
new Webpack.ProgressPlugin(),
new VueLoaderPlugin(),
],
}

此时再跑起来,发现没有报错了。

处理JS内容

我们平时在开发中肯定会用到ES6语法,这里我们也需要配置对应的loader来进行处理

安装babel-loader

npm i babel-loader @babel/preset-env @babel/core

配置

module.exports = {
module: {
rules: [
{
test: /.js$/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
},
exclude: /node_modules/
}
]
}
}

当然这里的options配置你也可以在.babelrcbabel.config.js中单独配置。

处理图片资源

与CSS一样,webpack也是默认不理解图片的,所以这里也需要配置loader进行处理。

webpack4

在webpack4中,我们常用的处理图片的loader有:file-loaderurl-loader

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

经过 file-loader 处理后,原始图片会被重命名并复制到产物文件夹,同时在代码中插入图片 URL 地址

  • url-loader 将文件作为 data URI 内联到 bundle 中,它有两种表现,对于小于阈值 limit 的图像直接转化为 base64 编码;大于阈值的图像则调用 file-loader 进行加载
module.exports = {
// ...
module: {
rules: [{
test: /.(png|jpg|gif|jpeg)$/,
use: [{
loader: 'url-loader',
options: {
limit: 1024
}
}]
}],
},
};

经过 url-loader 处理后,小于 limit 参数即 1024B 的图片会被转译为 Base64 编码,对于超过 limit 值的图片则直接调用 file-loader 完成加载。

webpack5

file-loaderurl-loader并不局限于处理图片,它们还可以被用于加载任意类型的多媒体或文本文件,使用频率极高,几乎已经成为标配组件!所以 Webpack5 直接内置了这些能力,开箱即可使用。

用法上,原本需要安装、导入 Loader,Webpack5 之后只需要通过 module.rules.type 属性指定资源类型即可

比如:

module.exports = {
// ...
module: {
rules: [{
test: /.(png|jpg|gif|jpeg)$/,
type: 'asset/resource'
}],
},
};

运行页面

配置了这么多内容,我们却还不能看到页面的内容,心里肯定不乐意,上面这几步操作其实就相当于翻译 Vue SFC 文件的内容,接下来我们还需要让页面真正运行起来。

粗暴方案

有一种快速验证我们的打包配置是否正确:我们只需要新建一个html文件,将打包产物引入进去,并创建好挂载节点就可以

<!-- public/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>
<div id="app"></div>
<script src="../dist/bundle.42603d.js"></script>
</body>
</html>

我们再把这个html文件在浏览器打开,就能看到我们vue项目能够正常打开了。

这种方案有一种弊端就是:我们打包出来的文件一般都会带有hash,那就需要我们每次在打包完后去html文件修改引入的文件,这样是不是有点太费劲了,你们能忍吗?

优雅方案

上面那种方案在日常开发中显然是不能接受的,身为程序员能偷懒的地方必须得偷懒!

我们可以利用下面两个工具让这个过程变得更加智能化、自动化。

html-webpack-plugin: 自动生成 HTML 页面

HtmlWebpackPlugin 简化了 HTML 文件的创建,以便为你的 webpack 包提供服务。这对于那些文件名中包含哈希值,并且哈希值会随着每次编译而改变的 webpack 包特别有用。

webpack-dev-server :让页面真正运行起来,并具备热更新能力。

webpack-dev-server 主要提供两种功能:

  • 结合 Webpack 工作流,提供基于 HTTP(S) 协议的静态资源服务;
  • 提供资源热更新能力,在保持页面状态前提下自动更新页面代码,提升开发效率。

安装

npm i html-webpack-plugin webpack-dev-server

修改配置


const Webpack = require('webpack')
const {VueLoaderPlugin}  = require('vue-loader')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
   entry: './src/main.js',
   output: {
       filename: 'bundle.[hash:6].js',
       path: __dirname + '/dist',
  },
   module: {
       rules:[
          {test: /.vue$/, use: 'vue-loader'},
          {
               test: /.css$/,
               use: ['style-loader', 'css-loader']
          },
          {
               test: /.js$/,
               use: {
                   loader: 'babel-loader',
                   options: {
                       presets: ['@babel/preset-env']
                  }
              },
               exclude: /node_modules/
          },
          {
               test: /.(png|jpg|gif|jpeg)$/,
               type: 'asset/resource',
          }
      ]
  },
   plugins:[
       new Webpack.ProgressPlugin(),
       new VueLoaderPlugin(),
       new HtmlWebpackPlugin({
           template: './public/index.html',
           filename: 'index.html'
      })
  ],
   devServer: {
       hot: true,
       open: true
  }
}

修改启动脚本

"dev": "webpack serve --mode development"

运行

npm run dev

这时webpack就能自动帮我们打开浏览器运行页面了

vue文件内容如下:

<template>
   <div class="title">webpack + vue -- {{ name }}</div>
   <img src="../asset/1.png" class="top_bg" />
</template>

<script setup>
import { ref } from 'vue'
const name = ref('前端南玖')
</script>

<style>
.title {
   font-size: 16px;
   font-weight: bold;
   color: salmon;
}
.top_bg {
   width: 100%;
   height: auto;
}
</style>

如果这篇文章有帮助到你,️关注+点赞️鼓励一下作者,文章公众号首发,关注 前端南玖 第一时间获取最新文章~

【webpack系列】从核心概念到上手配置的更多相关文章

  1. webpack安装与核心概念

    安装webpack webpack核心概念:入口.输出.加载器.插件.模块.模式 一.安装webpack 1.安装webpack之前需要安装nodejs环境,在使用nodejs环境自带的包管理工具np ...

  2. webpack 四个核心概念

    webpack 是当下最热门的前端资源模块化和打包工具.它可以将许多松散的模块(如 CommonJs 模块. AMD 模块. ES6 模块.CSS.图片. JSON.Coffeescript. LES ...

  3. Spring源码系列:核心概念解析

    前言 本文旨在为读者解析Spring源码中的关键类,以便读者在深入阅读源码时,能够了解关键类的作用和用途.在阅读Spring源码时,经常会遇到一些不熟悉的概念,了解关键类的作用可以帮助读者更好地理解这 ...

  4. webpack的四大核心概念

    webpack中文文档:https://doc.webpack-china.org/concepts/ 一.Entry(入口) 1.单个入口(简写)语法 // 语法 entry: string|Arr ...

  5. Storm概念学习系列之核心概念(Tuple、Spout、Blot、Stream、Stream Grouping、Worker、Task、Executor、Topology)(博主推荐)

    不多说,直接上干货! 以下都是非常重要的storm概念知识. (Tuple元组数据载体 .Spout数据源.Blot消息处理者.Stream消息流 和 Stream Grouping 消息流组.Wor ...

  6. 全文检索引擎Solr系列——Solr核心概念、配置文件

    Document Document是Solr索引(动词,indexing)和搜索的最基本单元,它类似于关系数据库表中的一条记录,可以包含一个或多个字段(Field),每个字段包含一个name和文本值. ...

  7. webpack核心概念

    一.webpack四个核心概念 1.入口[Entry] webpack将创建所有应用程序 依赖关系图表.图表的起点被称之为 入口起点.入口起点告诉webpack从哪里开始,并遵循着依赖关系图表知道打包 ...

  8. webpack系列之loader的基本使用

    可以访问 这里 查看更多关于大数据平台建设的原创文章. webpack系列之loader及简单的使用 一. loader有什么用 webpack本身只能打包Javascript文件,对于其他资源例如  ...

  9. webpack的四个核心概念介绍

    前言 webpack 是一个当下最流行的前端资源的模块打包器.当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后 ...

  10. 通过核心概念了解webpack工作机制

    webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler).当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency gr ...

随机推荐

  1. 【Vue原理模拟】模拟Vue实现响应式数据

    1. 预期效果 当数据变动时,触发自定义的回调函数. 2. 思路 对对象 object 的 setter 进行设置,使 setter 在赋值之后执行回调函数 callback(). 3.细节 3.1 ...

  2. 列表、sort、reverse、元组、字典、

    1.列表是一种有序可变的容器.通过[]来标识 1)定义一个空列表list = [] 2.列表的添加 1)末尾添加append() list = ['张三',,'王五'] list.append('刘六 ...

  3. 在idea中将一个javase项目转成ee项目

    在idea中将java项目转成web项目 1.创建一个java项目,new一个directory名为web(与src同级) 2. 为web指定根目录:ctrl+shift+alt+s,在module中 ...

  4. day14:列表/集合/字典推导式&生成器表达式&生成器函数

    推导式 推导式的定义: 通过一行循环判断,遍历一系列数据的方式 推导式的语法: val for val in Iterable 三种方式: [val for val in Iterable] {val ...

  5. ES的索引结构与算法解析

    作者:京东物流 李洪吉 提到ES,大多数爱好者想到的都是搜索引擎,但是明确一点,ES不等同于搜索引擎.不管是谷歌.百度.必应.搜狗为代表的自然语言处理(NLP).爬虫.网页处理.大数据处理的全文搜索引 ...

  6. 笔记十:线程间的通信(pthread_exit()和pthread_join())

    linux高级编程之线程间的通信(pthread_exit()和pthread_join()) 1.线程终止      如果进程中的任一线程调用了exit._Exit或者_exit,那么整个进程就会终 ...

  7. Prism Sample 11-UsingDelegateCommands

    本例的知识点,全在ViewModel中,看代码: 1 public class MainWindowViewModel : BindableBase 2 { 3 private bool _isEna ...

  8. Prism Sample 10 10-CustomRegistrations

    作用同上节,这里是用修改注册的方式自定义View和ViewModel的关联. protected override void ConfigureViewModelLocator() { base.Co ...

  9. Nginx Web快速入门

    Nginx Web快速入门 目录 Nginx Web快速入门 Nginx概述 为什么选择Nginx服务 Nginx的应用场景 源码安装nginx Yum安装nginx Nginx相关命令总结 Ngin ...

  10. 2023-03-21:音视频解混合(demuxer)为MP3和H264,用go语言编写。

    2023-03-21:音视频解混合(demuxer)为MP3和H264,用go语言编写. 答案2023-03-21: 步骤1:安装github.com/moonfdd/ffmpeg-go go get ...