webpack笔记-webpack基础用法(二)
webpack 本质上是一个打包工具,它会根据代码的内容解析模块依赖,帮助我们把多个模块的代码打包。

一切文件:JavaScript、CSS、SCSS、图片、模板,在 Webpack 眼中都是一个个模块,这样的好处是能清晰的描述出各个模块之间的依赖关系,以方便 Webpack 对模块进行组合和打包。 经过 Webpack 的处理,最终会输出浏览器能使用的静态资源。
entry
webpack 构建的入口entry,webpack 会读取这个文件,并从它开始解析依赖,在内部构件一个依赖图,这个依赖图会引用项目中使用到的各个模块,然后进行打包,生成一个或者多个 bundle 文件。
我们常见的项目中,如果是单页面应用,那么入口只有一个;如果是多个页面的项目,那么通常是一个页面会对应一个构建入口。
单⼊⼝:entry 是⼀个字符串,如下代码:
module.exports = {
entry: './src/index.js'
};
上述代码等价于:
// 上述配置等同于
module.exports = {
entry: {
main: './src/index.js'
}
}
多⼊口:entry 是⼀个对象,如下代码:
module.exports = {
entry: {
app: './src/app.js',
home: './src/home.js'
}
};
还有一种场景比较少用到,即是多个文件作为一个入口来配置,webpack 会解析多个文件的依赖然后打包到一起:
// 使用数组来对多个文件进行打包
module.exports = {
entry: {
main: [
'./src/foo.js',
'./src/bar.js'
]
}
}
动态 entry
const path = require('path');
const fs = require('fs');
// src/pages 目录为页面入口的根目录
const pagesRoot = path.resolve(__dirname, './src/pages');
// fs 读取 pages 下的所有文件夹来作为入口,使用 entries 对象记录下来
const entries = fs.readdirSync(pagesRoot).reduce((entries, page) => {
// 文件夹名称作为入口名称,值为对应的路径,可以省略 `index.js`,webpack 默认会寻找目录下的 index.js 文件
entries[page] = path.resolve(pagesRoot, page);
return entries;
}, {});
module.exports = {
// 将 entries 对象作为入口配置
entry: entries,
// ...
};
output
output用来告诉 webpack 如何将编译后的文件输出到磁盘。webpack 构建生成的文件名、路径等都是可以配置的,在配置文件中使用 output 字段来进行设置:
module.exports = {
// ...
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
},
}
// 或者使用 entry 的名称
module.exports = {
entry: {
main: './src/index.js' // main 为 entry 的名称
},
output: {
filename: '[name].js', // 使用 [name] 来引用 entry 名称,在这里即为 main
path: path.join(__dirname, '/dist/[hash]'),
// 路径中使用 hash,每次构建时会有一个不同 hash 值,可以用于避免发布新版本时浏览器缓存导致代码没有更新
// 文件名中也可以使用 hash
},
}
loader
我们在前端构建中会遇见需要使用各式各样的文件,例如 css 代码,图片,模板代码等。webpack 中提供一种处理多种文件格式的机制,便是使用 loader。我们可以把 loader 理解为是一个转换器,负责把某种文件格式的内容转换成 webpack 可以支持打包的模块。例如我们需要 css-loader 来处理 .css 文件(这里其实还需要 style-loader),最终把不同格式的文件都解析成 js 代码,以便打包后在浏览器中运行。
webpack 开箱即用只支持 JS 和 JSON 两种文件类型,通过 Loaders 去支持其它文件类型并且把它们转化成有效的模块,并且可以添加到依赖图中。
本身是一个函数,接受源文件作为参数,返回转换的结果。
常见的 Loaders 有哪些?
- babel-loader:转换ES6、ES7等JS新特性语法
- css-loader:支持.css文件的加载和解析
- less-loader:将less文件转换成css
- ts-loader:将TS转换成JS
- file-loader:进行图片、字体等的打包
- raw-loader:将文件以字符串的形式导入
- thread-loader:多线程打包JS和CSS
下面我们来配置下处理css的loader以及ES6转ES5的loader,首先npm安装如下loader,
- css-loader:npm i style-loader css-loader -D
- babel-loader:npm install babel-loader @babel/core @babel/preset-env
babel的一系列工具链说明:
@babel/core:
@babel/core是babel的核心库,所有的核心Api都在这个库里,这些Api供babel-loader调用;
@babel/preset-env:
这是一个预设的插件集合,包含了一组相关的插件,Bable中是通过各种插件来指导如何进行代码转换。该插件包含所有es6转化为es5的翻译规则。
babel官网对此进行的如下说明:
Transformations come in the form of plugins, which are small JavaScript programs that instruct Babel on how to carry out transformations to the code. You can even write your own plugins to apply any transformations you want to your code. To transform ES2015+ syntax into ES5 we can rely on official plugins like
@babel/plugin-transform-arrow-functions
大致即es6到es5的语法转换是以插件的形式实现的,可以是自己的插件也可以是官方提供的插件如箭头函数转换插件@babel/plugin-transform-arrow-functions。
由此我们可以看出,我们需要转换哪些新的语法,都可以将相关的插件一一列出,但是这其实非常复杂,因为我们往往需要根据兼容的浏览器的不同版本来确定需要引入哪些插件,为了解决这个问题,babel给我们提供了一个预设插件组,即@babel/preset-env,可以根据选项参数来灵活地决定提供哪些插件。为此,我们往往做如下配置:

@babel/polyfill:
@babel/preset-env只是提供了语法转换的规则,但是它并不能弥补浏览器缺失的一些新的功能,如一些内置的方法和对象,如Promise,Array.from等,此时就需要polyfill来做js得垫片,弥补低版本浏览器缺失的这些新功能。
我们需要注意的是,polyfill的体积是很大的,如果我们不做特殊说明,它会把你目标浏览器中缺失的所有的es6的新的功能都做垫片处理。但是我们没有用到的那部分功能的转换其实是无意义的,造成打包后的体积无谓的增大,所以通常,我们会在presets的选项里,配置"useBuiltIns": "usage",这样一方面只对使用的新功能做垫片,另一方面,也不需要我们单独引入import '@babel/polyfill'了,它会在使用的地方自动注入。
babel-loader:
以上@babel/core、@babel/preset-env 、@babel/polyfill其实都是在做es6的语法转换和弥补缺失的功能,但是当我们在使用webpack打包js时,webpack并不知道应该怎么去调用这些规则去编译js。这时就需要babel-loader了,它作为一个中间桥梁,通过调用babel/core中的api来告诉webpack要如何处理js。
@babel/plugin-transform-runtime:
polyfill的垫片是在全局变量上挂载目标浏览器缺失的功能,因此在开发类库,第三方模块或者组件库时,就不能再使用babel-polyfill了,否则可能会造成全局污染,此时应该使用transform-runtime。transform-runtime的转换是非侵入性的,也就是它不会污染你的原有的方法。遇到需要转换的方法它会另起一个名字,否则会直接影响使用库的业务代码,
故开发类库,第三方模块或者组件库时使用transform-runtime,平常的项目使用babel-polyfill即可.
详细可参考文章:
- 《了解babel:polyfill、loader、 preset-env及 core之间的关系》
- 《详解babel8.X版本用法填坑(babel-loader , @babel/core , @babel/plugin-stransform-runtime, @babel/preset-env)》
rules的配置如下:
module: {
rules:[
{
test: /\.css$/,
use: ['style-loader','css-loader']
},
{
test: /\.jsx?$/, // 匹配文件路径的正则表达式,通常我们都是匹配文件类型后缀
exclude: /node_modules/, // 排除掉node_modules这个文件夹的js文件
include: [
path.resolve(__dirname,'src') // 指定哪些路径下的文件需要经过 loader 处理
],
use: { // 指定使用的 loader
loader: 'babel-loader', // babel-loader 可以使用 babel 来将 ES6 代码转译为浏览器可以执行的的 ES5 代码
options: {
presets: ['@babel/preset-env']
}
}
}
]
}
plugin
plugin 在 webpack 中的配置只是把实例添加到 plugins 字段的数组中。不过由于需要提供不同的功能,不同的 plugin 本身的配置比较多样化。
常用的plugin:
- CommonsChunkPlugin:将chunks相同的模块代码提取成公共js,webpack4.x版本使用optimization.SplitChunks
- cleanWebpackPlugin:清理构建目录
- ExtractTextWebpackPlugin:将CSS从bundle文件里提取成一个独立的CSS文件(webpack3.x版本),webpack4.x版本使用mini-css-extract-plugin
- CopyWebpackPlugin:将文件或者文件夹拷贝到构建的输出目录
- HtmlWebpackPlugin:创建html文件去承载输出的bundle
- UglifyjsWebpackPlugin:压缩JS
- ZipWebpackPlugin:将打包出的资源生成一个zip包
const path = require('path');
module.exports = {
output: {
filename: 'bundle.js'
},
plugins: [
new HtmlWebpackPlugin({ // 放到plugins数组里
template: './src/index.html'
})
]
};
在 webpack 的构建流程中,plugin 用于处理更多其他的一些构建任务。可以这么理解,模块代码转换的工作由 loader 来处理,除此之外的其他任何工作都可以交由 plugin 来完成。
例如,使用 copy-webpack-plugin 来复制其他不需要 loader 处理的文件,只需在配置中通过 plugins 字段添加新的 plugin 即可:
npm install copy-webpack-plugin -D
# 插件通常为第三方的 npm package,都需要安装后才能使用
const CopyPlugin = require('copy-webpack-plugin');
module.exports = {
// ...
plugins: [
new CopyPlugin([
{ from: 'src/public', to: 'public' },
]),
],
};
mode
mode,构建模式是 webpack v4 引入的新概念,用于方便快捷地指定一些常用的默认优化配置,mode 可以是 development,production,none 其中的一个,我们之前已经在配置文件中添加了相应的配置:
module.exports = {
mode: 'development', // 指定构建模式为 development
// ...
}
顾名思义,development 模式用于开发时使用,production 模式用于线上生产时使用,none 则是不需要任何默认优化配置时使用。
development 和 production 模式的区别:
- 这两个模式会使用 DefinePlugin 来将 process.env.NODE_ENV 的值分别设置为 development 和 production,方便开发者在项目业务代码中判断当前构建模式。
- production 模式会启用 TerserPlugin来压缩JS代码,让生成的代码文件更小。
- development 模式会启用 devtools: 'eval' 配置,提升构建和再构建的速度。

前端构建基础配置
关联HTML
怎样将HTML引用路径和我们的构建结果关联起来,这个时候我们可以使用 html-webpack-plugin。
html-webpack-plugin 是一个独立的 package,在使用之前我们需要先安装它:
npm install html-webpack-plugin -D
然后在 webpack 配置中,将 html-webpack-plugin 添加到 plugins 列表中:
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
// ...
plugins: [
new HtmlWebpackPlugin({
template: 'src/index.html', // 配置文件模板
}),
],
}
这样,通过 html-webpack-plugin 就可以将我们的页面和构建 JS 关联起来,回归日常,从页面开始开发。如果需要添加多个页面关联,那么实例化多个 html-webpack-plugin, 并将它们都放到 plugins 字段数组中就可以了。
构建 CSS
我们编写 CSS,并且希望使用 webpack 来进行构建,为此,需要在配置中引入 loader 来解析和处理 CSS 文件:
module.exports = {
module: {
rules: {
// ...
{
test: /\.css/,
include: [
path.resolve(__dirname, 'src'),
],
use: [
'style-loader',
'css-loader',
],
},
},
}
}
上面配置的两个loader的作用:
- css-loader 负责解析 CSS 代码,主要是为了处理 CSS 中的依赖,例如 @import 和 url() 等引用外部文件的声明;
- style-loader 会将 css-loader 解析的结果转变成 JS 代码,运行时动态插入 style 标签来让 CSS 代码生效。
如果需要单独把 CSS 文件分离出来,我们需要使用 mini-css-extract-plugin 插件。
v4 版本之后才开始使用 mini-css-extract-plugin,之前的版本是使用 extract-text-webpack-plugin。
如下例子:
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
// ...
module: {
rules: [
{
test: /\.css/i,
use: [
// 因为这个插件需要干涉模块转换的内容,所以需要使用它对应的 loader
MiniCssExtractPlugin.loader,
'css-loader',
],
},
],
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].css' // 这里也可以使用 [hash]
}), // 将 css 文件单独抽离的 plugin
]
};
在上述使用 CSS 的基础上,通常我们会使用 Less/Sass 等 CSS 预处理器,webpack 可以通过添加对应的 loader 来支持,以使用 Less 为例
less-loader 只是 webpack 的转换器,启动 Less 你还需要安装 less 自身,同样地,sass-loader 也是这般。
在 webpack 配置中,添加一个配置来支持解析后缀为 .less 的文件:
module.exports = {
// ...
module: {
rules: [
{
test: /\.(less|css)$/,
use: [
// 因为这个插件需要干涉模块转换的内容,所以需要使用它对应的 loader
MiniCssExtractPlugin.loader,
'css-loader',
'less-loader',
],
},
],
},
// ...
}
处理图片文件
在前端项目的样式中总会使用到图片,虽然我们已经提到 css-loader 会解析样式中用 url() 引用的文件路径,但是图片对应的 jpg/png/gif 等文件格式,webpack 处理不了。是的,我们只要添加一个处理图片的 loader 配置就可以了,现有的 file-loader 就是个不错的选择。
file-loader 可以用于处理很多类型的文件,它的主要作用是直接输出文件,把构建后的文件路径返回。配置很简单,在 rules中添加一个字段,增加图片类型文件的解析配置:
module.exports = {
// ...
module: {
rules: [
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'file-loader',
options: {},
},
],
},
],
},
}
使用babel
Babel 是一个让我们能够使用 ES 新特性的 JS 编译工具,我们可以在 webpack 中配置 Babel,以便使用 ES6、ES7 标准来编写 JS 代码。
module.exports = {
// ...
module: {
rules: [
{
test: /\.jsx?/, // 支持 js 和 jsx 文件,使用 react 时需要
include: [
path.resolve(__dirname, 'src'), // 指定哪些路径下的文件需要经过 loader 处理
],
use: {
loader: 'babel-loader', // 指定使用的 loader
options: {
presets: ['@babel/preset-env'],
},
},
},
],
},
}
webpack笔记-webpack基础用法(二)的更多相关文章
- react基础用法二(组件渲染)
react基础用法二(组件渲染) 如图所示组件可以是函数 格式:function 方法名(){ return <标签>内容</标签>} 渲染格式: <方法名 /> ...
- Java并发编程笔记之基础总结(二)
一.线程中断 Java 中线程中断是一种线程间协作模式,通过设置线程的中断标志并不能直接终止该线程的执行,而是需要被中断的线程根据中断状态自行处理. 1.void interrupt() 方法:中断线 ...
- Bootstrap fileinput:文件上传插件的基础用法
官网地址:http://plugins.krajee.com/ 官网提供的样例:http://plugins.krajee.com/file-input/demo 基础用法一 导入核心CSS及JS文件 ...
- webpack笔记二 管理资源
webpack笔记二 管理资源 webpack最出色的功能之一就是除了引入JavaScript,还可以通过loader引入任何其它类型的文件. 加载CSS 为了在JavaScript模块中import ...
- Webpack笔记(二)——搭建React开发环境
前几天一直在学习webpack,总算比之前学习的时候有了点收获,所以在昨天发布了一篇webpack入门笔记,今天继续使用webpack练了练手,搭建了一个React开发环境,如果还不熟悉的童鞋可以看一 ...
- Webpack笔记(一)——从这里入门Webpack
准备了挺久,一直想要好好深入了解一下Webpack,之前一直嫌弃Webpack麻烦,偏向于Parcel这种零配置的模块打包工具一些,但是实际上还是Webpack比较靠谱,并且Webpack功能更加强大 ...
- webpack学习笔记—webpack安装、基本配置
文章结构: 什么是webpack? 安装webpack 'webpack基本配置 一.什么是webpack? 在学习react时发现大部分文章都是react和webpack结合使用的,所以在学reac ...
- 初识webpack——webpack四个基础概念
前面的话 webpack是当下最热门的前端资源模块化管理和打包工具.它可以将许多松散的模块按照依赖和规则打包成符合生产环境部署的前端资源.当webpack处理应用程序时,它会递归地构建一个依赖关系图表 ...
- 基于webpack的React项目搭建(二)
前言 前面我们已经搭建了基础环境,现在将开发环境更完善一些. devtool 在开发的过程,我们会经常调试,so,为了方便我们在chrome中调试源代码,需要更改webpack.config.js,然 ...
- 深入浅出的webpack构建工具---DevServer配置项(二)
深入浅出的webpack构建工具---DevServer配置项(二) 阅读目录 DevServer配置项 1. contentBase 2. port 3. host 4. headers 5. hi ...
随机推荐
- 【java深入学习第1章】深入探究 MyBatis-Spring 中 SqlSession 的原理与应用
前言 在使用 MyBatis 进行持久层开发时,通常会与 Spring 框架集成,以便更好地管理事务和依赖注入.在 MyBatis-Spring 集成中,SqlSession 是一个非常重要的概念.本 ...
- oeasy教您玩转vim - 39 - # 剪切粘贴
剪切粘贴 回忆上节课内容 我们大幅度地复习了整个 motion: 直接运动 h j k l 行运动 首行g g 末行G 第n行n G 单词运动 wbe w 是到下一个 word 的开头 b 是到当 ...
- 写几个有用的lambda
List<String> list = Arrays.asList("app", "ban", "ora"); //循环输出 f ...
- WorPress基础之谷歌GSC与GA统计代码安装
本篇文章讲介绍什么是GSC和GA以及如何安装. 什么是GSC GSC,全称为Google Search Console,由谷歌官方提供的网站管理工具,可帮助监控和维护网站在Google 搜索结果中的展 ...
- ChatGPT的作用(附示例)
ChatGPT介绍(内容由ChatGPT生成) ChatGPT是一款基于GPT(生成式预测网络)的聊天机器人,它可以根据用户输入自动生成相应的回复. GPT是由OpenAI开发的一种预测网络模型,其中 ...
- JDK安装教程(Windows)
Windows 端: 1. 安装 首先进入官网:https://www.oracle.com/java/technologies/javase-downloads.html 因为我已经安装了 JDK8 ...
- android 点击退出按钮 结束所有的activity 回到手机主页面
android 点击退出按钮 结束所有的activity 回到手机主页面我 实现了回到主页面 但是在点击这个程序 他还是回到**退出的界面 ** 我要实现点击按钮回到手机主页面 在点击这个程序后就重新 ...
- Jmeter固定定时器
固定定时器(Constant Timer),每个线程在请求之间暂停相同的时间.时间单位是毫秒,1000毫秒=1秒 组件路径:线程组->右键添加->定时器->固定定时器 1.固定定时器 ...
- 【Java】Properties 配置信息类
Properties 配置信息类 Properties 是HashTable的子类,该对象用于处理属性文件 由于属性文件的Key.Value都是字符串类型,所以Properties里的Key和Valu ...
- 【Web】 抓包工具Charles
官方软件包下载 https://www.charlesproxy.com/download/ 在线生成激活码: https://www.zzzmode.com/mytools/charles/ 代理设 ...