webpack讲解(完结篇)

Posted stay_少年与梦

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了webpack讲解(完结篇)相关的知识,希望对你有一定的参考价值。

文章目录


前言

这篇文章我们主要讲解一下webpack剩余的一些知识点,其中包括了plugin,是一个webpack的插件,我们会在这一篇中详细讲解一下

一、plugins

插件,通常是用于对某个现有的架构进行扩展
扩展 webpack 本身的一些功能,它们会运行在各种模块解析完成以后的打包编译阶段,比如对解析后的模块文件进行压缩等

loader和plugin 的区别

loader主要用于某些需要转换的模块,它是一个转换器
plugin是插件,它是对webpack本身的扩展,是一个扩展器

htmlWebpackPlugin

作用

在打包结束后,⾃动生成⼀个 html ⽂文件,并把打包生成的 js 模块引⼊到该 html

二、使用步骤

1.安装

在终端内输入

npm install --save-dev html-webpack-plugin

进行安装

2.引入

webpack.config.js文件下

const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = 
	...
  plugins: [
     new HtmlWebpackPlugin(
       title: "My App", //文件标题
       filename: "app.html", //打包好的html名
       template: "./public/index.html" //原地址文件(把谁打包)
     ) 
  ]
;

html 模板中,可以通过 <%=htmlWebpackPlugin.options.XXX%> 的方式获取配置的值

上面的title想要使用的话,我们需要在原地址index.htmltitle标签变为

  <title><%=htmlWebpackPlugin.options.title%></title>

现在我们执行打包命令后,它会自动生成一个文件,会出现如下(效果图)

这样我们就可以直接打开该文件,在页面中直接运行

更多的配置

  • title: ⽤来生成⻚面的 title 元素
  • filename: 输出的 HTML ⽂件名,默认是 index.html, 也可以直接配置子目录
  • template: 模板⽂件路径,⽀持加载器(loader),⽐如 html!./index.html
  • inject: true | 'head' | 'body' | false,注⼊所有的资源到特定的 template 或者 templateContent 中,如果设置为 true 或者 body,所有的 javascript 资源将被放置到 body 元素的底部,'head' 将放置到 head 元素中
  • favicon: 添加特定的 favicon 路径到输出的 HTML 文件中
  • minify: | false, 传递 html-minifier 选项给 minify 输出
  • hash: true | false,如果为 true,将添加 webpack 编译生成的 hash 到所有包含的脚本和 CSS ⽂件,对于解除 cache 很有用
  • cache: true | false,如果为 true,这是默认值,仅在文件修改之后才会发布文件
  • showErrors: true | false,如果为 true,这是默认值,错误信息会写入到 HTML ⻚面中
  • chunks: 允许只添加某些块 (⽐如,仅 unit test 块)
  • chunksSortMode: 允许控制块在添加到⻚面之前的排序方式,⽀持的值:'none' | 'default' |function-default:'auto'
  • excludeChunks: 允许跳过某些块,(⽐如,跳过单元测试的块)

clean-webpack-plugin

作用

删除(清理)构建目录

1.安装

npm install --save-dev clean-webpack-plugin

2.使用

webpack.config.js文件下写

const CleanWebpackPlugin = require('clean-webpack-plugin');
module.exports = 
	...
  plugins: [
    ...,
    new CleanWebpackPlugin(),
    ...
  ]

在这里设置打包后的路径

运行打包指令后,会发现现在打包后的文件会按照你写的路径自动添加好(效果图)

mini-css-extract-plugin

作用

提取 CSS 到一个单独的文件中

1.安装

npm install --save-dev mini-css-extract-plugin

2.使用

webpack.config.js文件下写

const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = 
	...,
  module: 
  	rules: [
  		
  			test: /\\.s[ac]ss$/,
  			use: [
  				
  					loader: MiniCssExtractPlugin.loader
					,
          'css-loader',
          'sass-loader'
        ]
			
  	]
	,
  plugins: [
    ...,
    new MiniCssExtractPlugin(
    	filename: '[name].css' //写你要打包到的路径(示例:public/css/app.css)
    ),
    ...
  ]

sourceMap

我们实际运行在浏览器的代码是通过 webpack 打包合并甚至是压缩混淆过的代码,所生成的代码并不利于我们的调试和错误定位,我们可以通过 sourceMap 来解决这个问题,sourceMap 本质是一个记录了编译后代码与源代码的映射关系的文件,我们可以通过 webpackdevtool 选项来开启 sourceMap

webpack.config.js文件下写

module.exports = 
  mode: 'production',
  devtool: 'source-map',
  ...

首先,编译后会为每一个编译文件生成一个对应的 .map 文件,同时在编译文件中添加一段对应的 map 文件引入代码

...
//# sourceMappingURL=xx.js.map
...
/*# sourceMappingURL=xx.css.map*/

同时,现代浏览器都能够识别 sourceMap 文件,如 chrome,会在 Sources 面板中显示根据编译文件与对应的 map 文件定位到源文件中,有利于我们的调试和错误定位

WebpackDevServer(热更新)

每次的代码修改都需要重新编译打包,刷新浏览器,有些麻烦,我们可以通过安装 webpackDevServer 来改善这方面的体验

安装

npm install --save-dev webpack-dev-server

启动命令:

npx webpack-dev-server

或者,也可以在package.json 中添加 scripts

...,
"scripts": 
  "server": "webpack-dev-server"

修改 webpack.config.js

module.exports = 
  ...,
  devServer: 
  	// 生成的虚拟目录路径
  	contentBase: "./dist",
  	// 自动开启浏览器
  	open: true,
  	// 端口
  	port: 8081
	

启动服务以后,webpack 不在会把打包后的文件生成到硬盘真实目录中了,而是直接存在了内存中(同时虚拟了一个存放目录路径),后期更新编译打包和访问速度大大提升

个人理解

就是在你保存代码的同时,会自动执行打包命令,并刷新网页内容,更加的方便,简单。

Proxy

作用

用来解决处理一些后端请求的时候出现跨域的问题

当下前端的开发都是前后端分离开发的,前端开发过程中代码会运行在一个服务器环境下(如当前的 WebpackDevServer),那么在处理一些后端请求的时候通常会出现跨域的问题。WebpackDevServer 内置了一个代理服务,通过内置代理就可以把我们的跨域请求转发目标服务器上(WebpackDevServer 内置的代理发送的请求属于后端 - node,不受同源策略限制),具体如下:

后端代码,以 node 为例

const Koa = require('koa');
const KoaRouter = require('koa-router');

const app = new Koa();
const router = new KoaRouter();

router.get('/api/info', async ctx => 
    ctx.body = 
        username: 'zMouse',
        gender: 'male'
    
)

app.use( router.routes() );
app.listen(8787);

前端代码

axios(
  url: 'http://localhost:8787/api/info'
).then(res => 
  console.log('res',res.data);
)

默认情况下,该代码运行以后会出现跨域请求错误,修改 webpack 配置

module.exports = 
  ...,
  devServer: 
  	// 生成的虚拟目录路径
  	contentBase: "./dist",
  	// 自动开启浏览器
  	open: true,
  	// 端口
  	port: 8081,
  	proxy: 
      '/api': 
      	target: 'http://localhost:8787'
    	
    
	

通过 proxy 设置,当我们在当前 WebpackDevServer 环境下发送以 /api 开头的请求都会被转发到 http://localhost:8787 目标服务器下

修改前端代码

axios(
  //url: 'http://locahost:8081/api/info',
  url: '/api/info'
).then(res => 
  console.log('res',res.data);
)

注意 url 地址要填写 WebpackDevServer 域,比如当前 WebpackDevServer 开启的是 http://localhost:8081,也就是我们当前前端代码运行的环境,那么请求的 url 也必须发送到这里,当我们的请求满足了 proxy 中设置的 /api 开头,那么就会把请求转发到 target ,所以最后的实际请求是:http://lcoahost:8787/api/info

Hot Module Replacement

作用

只会更新变化的部分

在之前当代码有变化,我们使用的 live reload,也就是刷新整个页面,虽然这样为我们省掉了很多手动刷新页面的麻烦,但是这样即使只是修改了很小的内容,也会刷新整个页面,无法保持页面操作状态。HMR 随之就出现了,它的核心的局部(模块)更新,也就是不刷新页面,只更新变化的部分

module.exports = 
  ...,
  devServer: 
  	// 生成的虚拟目录路径
  	contentBase: "./dist",
  	// 自动开启浏览器
  	open: true,
  	// 端口
  	port: 8081,
  	// 开启热更新
  	hot:true,
  	// 即使 HMR 不生效,也不去刷新整个页面(选择开启)
    hotOnly:true,
  	proxy: 
      '/api': 
      	target: 'http://localhost:8787'
    	
    
	

开启 HMR 以后,当代码发生变化,webpack 即会进行编译,并通过 websocket 通知客户端(浏览器),我们需要监听处理来自 webpack 的通知,然后通过 HMR 提供的 API 来完成我们的局部更新逻辑

export default function() 
    console.log('start1!');

index.js代码

import fn1 from './fn1.js';
box1.onclick = fn1;

if (module.hot) //如果开启 HMR
    module.hot.accept('./fn1.js', function() 
      // 更新逻辑
      box1.onclick = fn1;
    )

上面的代码就是 当 ./fn1.js 模块代码发生变化的时候,把最新的 fn1 函数绑定到 box1.onclick 上

从上面我们看到,HMR 其实就是以模块为单位,当模块代码发生修改的时候,通知客户端进行对应的更新,而客户端则根据具体的模块来更新我们的页面逻辑(这些逻辑需要自己去实现)。

WebpackDevServer与Hot Module Replacement的区别

共同点:都可以自动打包并刷新页面内容。
不同点:WebpackDevServer每一次都是整体刷新页面,即使只是修改了很小的内容,也会刷新整个页面,无法保持页面操作状态。
Hot Module Replacement:它的核心的局部(模块)更新,也就是不刷新页面,只更新变化的部分。


总结

今天主要讲了webpack的插件和webpack的热更新,到了今天,分为了4篇内容把webpack的内容讲完了,说一下webpack的主要作用吧
  • webpack可以根据模板生成HTML,并自动处理上面的css/js引用路径。
  • webpack可以自动处理里面的图片路径,css里面背景图的路径,字体引用。
  • webpack可以开启本地服务器,一边改写代码,一边自动更新页面内容。
  • webpack可以编译js es6 sass less 等,并添加了md5sourcemap等辅助功能。
  • webpack可以异步加载内容,不需要时可以不加载到DOM上。

webpack分为四个核心
Entry: 告诉webpack入口文件在哪
Output: 告诉webpack把编译好的文件打包后放在哪里
Loaders: 告诉webpack在添加到依赖图之前如何转换,比如es6转es5,sass转css。
Plugins: 在编译的过程中可以添加你想要的任何操作,loader做不了的事情它也可以做到。

说到这里,你是不是也觉得webpack很强大,

欢迎大家阅读访问,如果觉得写得不错,可以点赞加关注,有不足的地方,欢迎大家在评论区留言

以上是关于webpack讲解(完结篇)的主要内容,如果未能解决你的问题,请参考以下文章

玩转 webpack视频课程学习笔记合集(未完结)

webpack拓展篇(六十九):vite 的构建原理(完结)

云原生 | 从零开始学Kubernetes二十八完结篇—rbac授权深入讲解

安卓自定义View进阶 - Path之完结篇(伪)

安卓自定义View进阶 - Path之完结篇(伪)

DDD领域驱动之干货补充篇!