Webpack详解(一)https://developer.aliyun.com/article/1470453
(理解)webpack对图片资源的特殊处理
import "css文件的地址"//css文件引入js跟webpack形成依赖图(不需要额外配置) //创建div元素,设置背景 const divBgEl = document.createElement("div") divBgEl.classList.add('img-bg') document.body.append(divBgEl) //css文件 .bg-image{ background-image:url("../img/nhlt.jpg");//就是填入图片 width:500px; height:500px }
进行打包,图片会被重命名,是基于哈希算法生成的哈希值命名
//打包图片,并且这图片有自己的地址,将地址设置到img/bgi中(打包图片命名是哈希算法生成) type:"asset/resource" //对图片使用了base64编码,图片编译形成的源码内容放到了行内(也就是放到了js文件),所以打包的文件里面就看不到图片了,但js的文件就变得很大 type:"asset/inline" //base64编码优势:少发送 当前图片数量(比如两张图片就两次网络请求) 的网络请求,因为第一种方式图片放在服务器上后,要进行http请求图片,而base64就跟着js文件一起下载下来了 //base64编码的劣势:js文件变大,下载文件本身时间过长,造成js代码的下载和解析/执行时间过长。用户长时间都只能看着空白界面等待文件的下载 //合理的规范 //1.对于小一点的图片,可以进行base64编码 //2.对于大一点的图片,单独的图片打包,形成url地址,单独的请求这个url图片
url-loader的limit效果
- 开发中我们往往是小的图片需要转换,但是大的图片直接使用图片即可
- 这是因为小的图片转换base64之后可以和页面一起被请求,减少不必要的请求过程
- 而大的图片也进行转换,反而会影响页面的请求速度
- 我们需要两个步骤来实现:
- 步骤一:将type修改为asset;
- 步骤二:添加一个parser(解析)属性,并且制定dataUrl(地址数据)的条件,添加maxSize(最大的大小)属性
rules:[ { test:/\.(png|svg|jpg|jpe?g|gif)$/, type:"asset",//这是最好的选择,会自动选择合理的规范 generator:{ filename:"img/{name}.{hash:6}{ext}" }, parser:{ dataUrlCondition:{//数据地址条件 maxSize:100 * 1024//以什么尺寸作为分界线(单位是byte字节) } } } ]
(掌握)webpack对JS代码的babel处理
为什么需要babel?
- 事实上,在开发中我们很少直接去接触babel,但是babel对于前端开发来说,目前是不可缺少的一部分:
- 开发中,我们想要使用ES6+的语法,想要使用TypeScript,开发React项目,它们都是离不开Babel的
- 所以,学习Babel对于我们理解代码从编写到线上的转变过程至关重要
- 那么,Babel到底是什么呢?
- Babel是一个工具链,主要用于旧浏览器或者环境中将ECMAScript 2015+代码转换为向后兼容版本的JavaScript
- 包括:语法转换、源代码转换等
Babel命令行使用
- babel本身可以作为一个独立的工具(和postcss一样),不和webpack等构建工具配置来单独使用
- 如果我们希望在命令行尝试使用babel(也就是独立使用,不配合webpack使用),需要安装如下库:
- @babel/core:babel的核心代码,必须安装
- @babel/cli:可以让我们在命令行使用babel
- 使用babel来处理我们的源代码:
- src:是源文件的目录
- --out-dir:指定要输出的文件夹dist
npx babel src --out-dir dist
插件的使用
- 比如我们需要转换箭头函数,那么我们就可以使用箭头函数转换相关的插件:
npm install @babel/plugin-transform-arrow-functions -D npx babel src --out-dir dist --plugins=@babel/plugin-transform-arrow-functions
npx |
npx 是 npm 5.2.0 版本以上提供的命令行工具,用于在命令行中运行安装在本地的 node 模块。这里使用 npx 来运行 babel 命令,避免在全局安装 Babel 的情况下产生冲突 |
babel |
babel 是一个 JavaScript 编译器,可以将新版本的 JavaScript 代码转换为旧版本的语法,以确保代码能够在更多的浏览器或环境中运行。这里使用 babel 命令对指定目录下的 JavaScript 代码进行转换 |
src |
要转换的源代码目录 |
--out-dir dist |
指定转换后的代码输出到 dist 目录 |
@babel/plugin-transform-arrow-functions |
指定使用 @babel/plugin-transform-arrow-functions 插件来转换 ES6 箭头函数语法。该插件的作用是将箭头函数转换为普通的函数表达式,以确保代码能够在不支持箭头函数的环境中正常运行 |
- 查看转换后的结果:我们会发现 const 并没有转成 var
- 这是因为 plugin-transform-arrow-functions,并没有提供这样的功能
- 我们需要使用 plugin-transform-block-scoping 来完成这样的功能
npm install @babel/plugin-transform-block-scoping -D//转化const、let这些ES6语法 npx babel src --out-dir dist --plugins=@babel/plugin-transform-block-scoping ,@babel/plugin-transform-arrow-functions //es6的语法很多,要转化一个个的安装会很麻烦,而且到时候写进rules也会很多,所以我们除了等等会使用预设之外,我们还要将他跟刚刚一样抽取出去,让webpack.config.js更简洁一点。 //抽取到哪?当然是我们自己创建一个babel.config.js,然后放进去啦
//babel.config.js module.exports = { plugin:[ "@babel/plugin-transform-arrow-functions" "@babel/plugin-transform-block-scoping" ] }
然后就可以省略掉下面这部分
Babel的预设preset
- 但是如果要转换的内容过多,一个个设置是比较麻烦的,我们可以使用预设(preset):
- 安装 @babel/preset-env 预设,是指安装一个 Babel 预设模块,用于根据所配置的目标环境,自动选择并使用一组适用于目标环境的 Babel 插件。该预设包含了所有与 JavaScript 新语法相关的转换插件,并根据所配置的目标环境,自动选择需要的插件进行转换
- 后面我们再具体来写预设代表的含义
- 安装@babel/preset-env预设:
npm install @babel/preset-env -D
- 执行如下命令:
npx babel src --out-dir dist --presets=@babel/preset-env
- 安装完预设之后,我们刚刚创建的babel.config.js就需要做出一点转变了,因为预设(presets)跟配置(plugins)是分开的
module.exports = { //没有plugins了,有预设就不需要plugin了。他们是分开算的,但是预设里面已经基本包含了 presets:[ "@babel/preset-env" ] }
babel-loader
- 在实际开发中,我们通常会在构建工具中通过配置babel来对其进行使用的,比如在webpack中
- 那么我们就需要去安装相关的依赖:
- 如果之前已经安装了@babel/core,那么这里不需要再次安装
npm install babel-loader -D
- 我们可以设置一个规则,在加载js文件时,使用我们的babel
module: [ rules: [ { test: /\.js$/, use: { loader: "babel-loader" } } ] ]
babel-preset
- 如果我们一个个去安装使用插件,那么需要手动来管理大量的babel插件,我们可以直接给webpack提供一个preset,webpack会根据我们的预设来加载对应的插件列表,并且将其传递给babel
- 比如常见的预设有三个:
- env(主要针对ES6语法)
- react
- TypeScript
- 安装preset-env:
npm install @babel/preset-env
(掌握)webpack对vue文件的处理打包
编写App.vue代码
- 在开发中我们会编写Vue相关的代码,webpack可以对Vue代码进行解析:
- 接下来我们编写自己的App.vue代码
App.vue的打包过程
- 我们对代码打包会报错:我们需要合适的Loader来处理文件
- 这个时候我们需要使用vue-loader:
npm install vue-loader -D
- 在webpack的模板规则中进行配置:
{ test:/\.js$/, loader:"vue-loader" }
@vue/compiler-sfc
- 打包依然会报错,这是因为我们必须添加@vue/compiler-sfc来对template进行解析:
npm install @vue/compiler-sfc -D
- 另外我们需要配置对应的Vue插件:
const {VueLoaderPlugin} = require('vue-loader/dist/index') new VueLoaderPlugin()
- 重新打包即可支持App.vue的写法
- 另外,我们也可以编写其他的.vue文件来编写自己的组件
(掌握)webpack对文件路径的解析和配置
resolve模块解析
- resolve用于设置模块如何被解析:
- 在开发中我们会有各种各样的模块依赖,这些模块可能来自于自己编写的代码,也可能来自第三方库
- resolve可以帮助webpack从每个 require/import 语句中,找到需要引入到合适的模块代码
- webpack 使用 enhanced-resolve 来解析文件路径
- webpack能解析三种文件路径:
- 绝对路径
- 由于已经获得文件的绝对路径,因此不需要再做进一步解析
- 相对路径
- 在这种情况下,使用 import 或 require 的资源文件所处的目录,被认为是上下文目录
- 在 import/require 中给定的相对路径,会拼接此上下文路径,来生成模块的绝对路径
- 模块路径(比如
import {createApp} from 'vue'
的vue就是一个模块路径,会去node_modules查找)
- 在 resolve.modules中指定的所有目录检索模块
默认值是 ['node_modules'],所以默认会从node_modules中查找文件 - 我们可以通过设置别名的方式来替换初识模块路径,具体后面讲解alias的配置
确定是文件还是文件夹
- 如果是一个文件:
- 如果文件具有扩展名(.js,.ts,.json这些),则直接打包文件;
- 否则,将使用 resolve.extensions选项作为文件扩展名解析 (extensions的中文意思是扩展)
- 如果是一个文件夹:
- 会在文件夹中根据 resolve.mainFiles配置选项中指定的文件顺序查找
resolve.mainFiles的默认值是 ['index'] (这就是我们引入文件夹下的index能够省略index的原因,因为这里默认找index)
再根据 resolve.extensions来解析扩展名
extensions和alias配置
- extensions是解析到文件时自动添加扩展名:
- 默认值是 ['.wasm', '.mjs', '.js', '.json']
- 所以如果我们代码中想要添加加载 .vue 或者 jsx 或者 ts 等文件时,我们必须自己写上扩展名
- 我们之前浅尝试了一下
import hello from "./xxx/Hello.vue"
的后缀.vue不能去掉就是因为我们没有配置extensions,如果配置了,下次我们就不需要加上.vue这个后缀了
- 另一个非常好用的功能是配置别名alias:
- 特别是当我们项目的目录结构比较深的时候,或者一个文件的路径可能需要 ../../../这种路径片段
- 我们可以给某些常见的路径起一个别名
//webpack.config.js文件 resolve:{//resolve用来解析模块的 extensions:[".wasm",".mjs",".js","vue","tsx"],//解析到对应文件就加上这些扩展名(这也是我们为什么可以引入省略.vue的原因) alias:{//给路径起别名,下次写的时候就能用@替代掉路径(在小满zs的Router4视频就有使用到这种方法) "@":resolveApp(__dirname,"./src/utils")//__dirname是用来获取当前的所在路径 pages:resolveApp("./src/pages") } }
Webpack常见的插件和模式
(理解)webpack中plugin的作用和loader
认识Plugin
- Webpack的另一个核心是Plugin,官方有这样一段对Plugin的描述:
- While loaders are used to transform certain types of modules, plugins can be leveraged to perform a wider range of tasks like bundle optimization, asset management and injection of environment variables
- 翻译:虽然加载器用于转换某些类型的模块,但可以利用插件执行更广泛的任务,如包优化、资产管理和环境变量注入
- 上面表达的含义翻译过来就是:
- Loader是用于特定的模块类型进行转换(但也就仅此而已了,所以Loader跟plugin是很不一样的)
然后复习下Loader的概念
npm install sass
安装的是 Sass 编译器,它是一个独立的工具,用于将 Sass/Scss 样式文件编译成 CSS 文件。 Sass 编译器能够将 Sass 语法或者 Scss 语法转换为 CSS 语法,并输出为 CSS 文件,方便浏览器或者其他设备渲染。在使用 Sass 编译器时,需要手动运行命令才能将 Sass/Scss 文件编译成 CSS 文件,而无法自动集成到 Webpack 构建流程中。
相比之下,Webpack 中的 sass-loader
是一个 Loader,可以集成到 Webpack 构建流程中,让 Webpack 能够将 Sass/Scss 样式文件编译成 CSS 文件。sass-loader
能够自动地将 Sass/Scss 文件编译成 CSS 文件,并将其打包进最终的 JavaScript 文件中,使得我们可以直接在浏览器中使用编译后的 CSS 文件。
在使用 Webpack 进行项目构建时,使用 sass-loader
能够使我们更方便地处理 Sass/Scss 样式文件,将其转换成能够直接在浏览器中使用的 CSS 文件,并能够将其集成到构建流程中,自动化地处理样式文件
- Plugin可以用于执行更加广泛的任务(能够贯穿整个webpack的周期),比如打包优化、资源管理、环境变量注入等
(掌握)webpack插件-Clean插件
CleanWebpackPlugin
- 前面我们演示的过程中,每次修改了一些配置,重新打包时,都需要手动删除dist文件夹:
- 我们可以借助于一个插件来帮助我们完成,这个插件就是CleanWebpackPlugin
CleanWebpackPlugin
是一个Webpack插件,用于在每次构建前清空输出目录。通过使用new
关键字来创建一个CleanWebpackPlugin
的实例,我们可以将其作为一个插件加入到Webpack构建流程中,让Webpack在每次构建之前自动清空输出目录。这样我们就能够保证输出目录中只包含最新的构建结果,而不会留下过时的文件
- 首先,我们先安装这个插件:
npm install clean-webpack-plugin -D
- 之后在插件中配置:
const {CleanWebpackPlugin} = require('clean-webpack-plugin') module.exports = { //其他省略 plugins:[ //Webpack的配置中,我们通常使用 new 关键字来创建一个Plugin实例 //在Webpack的配置中,Plugins通常是以实例化的形式添加到配置中的,这是因为插件实例化后可以传递一些参数,从而达到更加灵活的配置目的。同时,一个插件实例通常只能使用一次,因此需要在每个插件前使用 new 关键字来创建新的实例 new CleanWebpackPlugin() ] }
(掌握)webpack插件-Html插件
HtmlWebpackPlugin
- 另外还有一个不太规范的地方:
- 我们的HTML文件是编写在根目录下的,而最终打包的dist文件夹中是没有index.html文件的
- 在进行项目部署的时,必然也是需要有对应的入口文件index.html
- 所以我们也需要对index.html进行打包处理
- 对HTML进行打包处理我们可以使用另外一个插件:HtmlWebpackPlugin
npm install html-webpack-plugin -D
const HtmlWebpackPlugin = require('html-webpack-plugin') module.exports = { //其他省略 plugins:[ new HtmlWebpackPlugin({//使用之后,打包的时候,入口文件index.html也会被打包进去 title:"webpack案例"//这样可以生成index.html里面的标题<title>标题</title> template:"路径"//生成你自己指定的html模板(也就是下面的自定义模板) }) ] }
生成index.html分析
- 我们会发现,现在自动在dist文件夹中,生成了一个index.html的文件:
- 该文件中也自动添加了我们打包的bundle.js文件
- 这个文件是如何生成的呢?
- 默认情况下是根据ejs的一个模板来生成的
- 在html-webpack-plugin的源码中,有一个default_index.ejs模块
自定义HTML模板
- 如果我们想在自己的模块中加入一些比较特别的内容:
- 比如添加一个noscript标签,在用户的JavaScript被关闭时,给予响应的提示
- 比如在开发vue或者react项目时,我们需要一个可以挂载后续组件的根标签
- 这个我们需要一个属于自己的index.html模块:
自定义模板数据填充
- 上面的代码中,会有一些类似这样的语法<% 变量 %>,这个是EJS模块填充数据的方式
- 在配置HtmlWebpackPlugin时,我们可以添加如下配置:
- template:指定我们要使用的模块所在的路径
- title:在进行htmlWebpackPlugin.options.title读取时,就会读到该信息(代码块在上面了)
(掌握)webpack插件-Define插件
DefinePlugin的介绍
- 但是,这个时候编译还是会报错,因为在我们的模块中还使用到一个BASE_URL的常量:
- 这是因为在编译template模块时,有一个BASE_URL:
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
- 但是我们并没有设置过这个常量值,所以会出现没有定义的错误
- 这个时候我们可以使用DefinePlugin插件
DefinePlugin的使用
- DefinePlugin允许在编译时创建配置的全局常量,是一个webpack内置的插件(不需要单独安装):
const {DefinePlugin} = require('webpack'); module.exports = { //其他省略 plugins:[ new DefinePlugin({ //作用:直接注入全局,你可以在任何一个地方使用它 BASE_URL:'"./"'//因为是会将里面的内容直接当作一个代码来执行的,所以内部还需要""将./括起来才表示字符串 XiaoYu:"'小余全局都能看到'" })//因为插件都是类,所以需要使用new来构造使用 ] } //随意一个文件,使用用过DefinePlugin注入的变量 console.log(XiaoYu)//小余全局都能看到,不需要声明就可以直接打印,因为我们已经注入全局了 //判断是开发环境还是生产环境 console.log(process.env.NODE_DNV)
- 这个时候,编译template就可以正确的编译了,会读取到BASE_URL的值;
(理解)webpack模式-不同模式的作用
Mode配置
- 前面我们一直没有讲mode(模式的配置)
- Mode配置选项,可以告知webpack使用相应模式的内置优化:
- 默认值是production(什么都不设置的情况下)
- 可选值有:'none(什么都没)' | 'development(开发模式)' | 'production(生产模式)'
- 这几个选项有什么样的区别呢?
选项 |
描述 |
development |
会将 中 的值设置位 为模块(分包的)和chunk启用有效的名(能让你看懂的名字) |
production |
会将 中 的值设置位 。为模块和chunk启用确定性的混淆名称, , , , 和 |
none |
不使用任何默认优化选项 |
Mode配置代表更多
设置mode为'development'相当于设置了这些红色的部分
而当mode设置了'production'的时候,也相当设置了下面这些红色部分,是非常多的选项的
Webpack搭建本地服务器
补充打包dist前会将之前的内容先清空的另一种新的方式
(掌握)webpack开启本地服务器
为什么要搭建本地服务器?
- 目前我们开发的代码,为了运行需要有两个操作:
- 操作一:npm run build,编译相关的代码
- 操作二:通过live server或者直接通过浏览器,打开index.html代码,查看效果
- 这个过程经常操作会影响我们的开发效率(live server搭建的本地服务器在修改完代码需要重新打包才能够看到效果),我们希望可以做到,当文件发生变化时,可以自动的完成 编译 和 展示
- 为了完成自动编译,webpack提供了几种可选的方式:
- webpack watch mode(让webpack自动观察代码的变化)
- webpack-dev-server(常用,搭建本地服务,一旦代码发生变化就会自动的做一个编译,编译完直接在浏览器做一个刷新,就能够直接看到效果)
- webpack-dev-middleware
webpack-dev-server
- 上面的方式可以监听到文件的变化,但是事实上它本身是没有自动刷新浏览器的功能的:
- 当然,目前我们可以在VSCode中使用live-server来完成这样的功能
- 但是,我们希望在不适用live-server的情况下,可以具备live reloading(实时重新加载)的功能
- 安装webpack-dev-server
npm install webpack-dev-server -D
- 修改配置文件,启动时加上serve参数:
//在package.json文件中 "scripts":{ "serve":"webpack serve --config webpack.config.js"//命令作用就是搭建本地服务,我们放在scripts里面,方便使用npm run serve在终端快捷访问 }
webpack是怎么搭建本地服务器的:
- 不再对dits文件做单独的打包,因为webpack搭建出来的本地服务器能够自动的对src(也就是我们写的代码)进行打包,打包后不会生成对应的本地文件的(因为生成本地文件还需要写入本地文件外加读取本地文件,效率太低)。
- webpack打包好的东西如果不生成对应的本地文件的话,会在哪里?在内存里,是直接放到了内存里面,然后搭建的服务器直接从内存中读取,读取后放到服务器上面,然后浏览器对服务器做出请求就行了
- webpack-dev-server 在编译之后不会写入到任何输出文件,而是将 bundle 文件保留在内存中:
- 事实上webpack-dev-server使用了一个库叫memfs(memory-fs webpack自己写的)
(理解)webpack的热模块替换HMR
我们刚刚自动更新的方式是当我们修改了一个地方,会整个浏览器都更新了一遍,但这其实是没有必要的,会浪费性能而且保存的数据也会丢失,我们只需要更新我们修改的地方
认识模块热替换(HMR)
- 什么是HMR呢?
- HMR的全称是Hot Module Replacement,翻译为模块热替换
- 模块热替换是指在 应用程序运行过程中,替换、添加、删除模块,而无需重新刷新整个页面
- HMR通过如下几种方式,来提高开发的速度:
- 不重新加载整个页面,这样可以保留某些应用程序的状态不丢失
- 只更新需要变化的内容,节省开发的时间
- 修改了css、js源代码,会立即在浏览器更新,相当于直接在浏览器的devtools中直接修改样式
- 如何使用HMR呢?
- 默认情况下,webpack-dev-server已经支持HMR,我们只需要开启即可(默认已经开启)
开启HMR
- 修改webpack.config.js的配置:
module.exports = { //其他配置忽略 devServer:{ hot:true } }
- 浏览器可以看到如下效果:
- 但是你会发现,当我们修改了某一个模块的代码时,依然是刷新的整个页面:
- 这是因为我们需要去指定哪些模块发生更新时,进行HMR
if(module.hot){//判断有没有hot //指定哪一个模块需要HMR module.hot.accept("./util/math.js",()=>{//触发热更新 console.log("math更新了") }) } //此时还是会大部分刷新,那是因为你如果在math文件中引入其他文件(其中包括了入口文件,那差不多相当于全刷新了),webpack也会认为引入相关联的文件也要刷新,那这种情况怎么解决? //在util文件夹下创建一个demo.js文件,里面就啥都不写,然后将demo引入math文件中。然后我们将上面内容修改一下,改成热更新demo部分,这样demo带动math文件的更新 if(module.hot){//判断有没有hot //指定哪一个模块需要HMR module.hot.accept("./util/demo.js",()=>{ console.log("demo更新了") }) }
(了解)webpack的devServer配置信息
框架的HMR
- 有一个问题:在开发其他项目时,我们是否需要经常手动去写入 module.hot.accpet相关的API呢?
- 比如开发Vue、React项目,我们修改了组件,希望进行热更新,这个时候应该如何去操作呢?
- 事实上社区已经针对这些有很成熟的解决方案了:
- 比如vue开发中,我们使用vue-loader,此loader支持vue组件的HMR,提供开箱即用的体验
- 比如react开发中,有React Hot Loader,实时调整react组件(目前React官方已经弃用了,改成使用react-refresh)
host配置
- host设置主机地址:
- 默认值是localhost
- 如果希望其他地方也可以访问,可以设置为 0.0.0.0
//在webpack.config.js中进行设置 devServer:{ hot:true//就刚刚设置的开启热更新 port:8888//看你想要开启哪个端口,你也可以设置0.0.0.0(IP地址) }
- localhost 和 0.0.0.0 的区别:
- localhost:本质上是一个域名,通常情况下会被解析成127.0.0.1
- 127.0.0.1:回环地址(Loop Back Address),表达的意思其实是我们主机自己发出去的包,直接被自己接收;
正常的数据库包经常 应用层 - 传输层 - 网络层 - 数据链路层 - 物理层
而回环地址,是在网络层直接就被获取到了(会被自己捕获到),是不会经常数据链路层和物理层的
比如我们监听 127.0.0.1时,在同一个网段下的主机中,通过ip地址是不能访问的 - 0.0.0.0:监听IPV4上所有的地址,再根据端口找到不同的应用程序
比如我们监听 0.0.0.0时,在同一个网段下的主机中,通过ip地址是可以访问的
port、open、compress
- port设置监听的端口,默认情况下是8080
- open是否打开浏览器:
- 默认值是false,设置为true会打开浏览器(就是当你运行后自己打开浏览器)
- 也可以设置为类似于 Google Chrome等值
- compress是否为静态文件开启gzip compression:
- 默认值是false,可以设置为true(压缩文件的)
Proxy(Vue项目学习)
在Vue项目中再写详细的,暂时跳过
- proxy是我们开发中非常常用的一个配置选项,它的目的设置代理来解决跨域访问的问题:
- 比如我们的一个api请求是 http://localhost:8888,但是本地启动服务器的域名是 http://localhost:8000,这个时候发送网络请求就会出现跨域的问题;
- 那么我们可以将请求先发送到一个代理服务器,代理服务器和API服务器没有跨域的问题,就可以解决我们的跨域问题了
- 我们可以进行如下的设置:
- target:表示的是代理到的目标地址,比如 /api-hy/moment会被代理到 http://localhost:8888/api-hy/moment
- pathRewrite:默认情况下,我们的 /api-hy 也会被写入到URL中,如果希望删除,可以使用pathRewrite
- secure:默认情况下不接收转发到https的服务器上,如果希望支持,可以设置为false
- changeOrigin:它表示是否更新代理后请求的headers中host地址
changeOrigin的解析(Vue项目学习)
在Vue项目中再写详细的,暂时跳过
- 这个 changeOrigin官方说的非常模糊,通过查看源码我发现其实是要修改代理请求中的headers中的host属性:
- 因为我们真实的请求,其实是需要通过 http://localhost:8888来请求的
- 但是因为使用了代码,默认情况下它的值时 http://localhost:8000
- 如果我们需要修改,那么可以将changeOrigin设置为true即可
historyApiFallback (Vue项目学习)
- historyApiFallback是开发中一个非常常见的属性,它主要的作用是解决SPA页面在路由跳转之后,进行页面刷新时,返回404的错误
- boolean值:默认是false
- 如果设置为true,那么在刷新时,返回404错误时,会自动返回 index.html 的内容
- object类型的值,可以配置rewrites属性:
- 可以配置from来匹配路径,决定要跳转到哪一个页面
- 事实上devServer中实现historyApiFallback功能是通过connect-history-api-fallback库的:
- 可以查看connect-history-api-fallback 文档
如何区分开发环境
- 目前我们所有的webpack配置信息都是放到一个配置文件中的:webpack.config.js
- 当配置越来越多时,这个文件会变得越来越不容易维护
- 并且某些配置是在开发环境需要使用的,某些配置是在生成环境需要使用的,当然某些配置是在开发和生成环境都会使用的
- 所以,我们最好对配置进行划分,方便我们维护和管理
- 那么,在启动时如何可以区分不同的配置呢?
- 方案一:编写两个不同的配置文件,开发和生成时,分别加载不同的配置文件即可
- 方式二:使用相同的一个入口配置文件,通过设置参数来区分它们
"scripts":{ "build":"webpack --config ./config/common.config --env production", "serve":"webpack serve --config ./config/common.config" }
入口文件解析
- 我们之前编写入口文件的规则是这样的:./src/index.js,但是如果我们的配置文件所在的位置变成了 config 目录,我们是否应该变成 ../src/index.js呢?
- 如果我们这样编写,会发现是报错的,依然要写成 ./src/index.js
- 这是因为入口文件其实是和另一个属性时有关的 context
- context的作用是用于解析入口(entry point)和加载器(loader)
- 官方说法:默认是当前路径(但是经过coderwhy测试,默认应该是webpack的启动目录)
- 另外推荐在配置中传入一个值
//context是配置文件所在目录 module.exports = { context:path.resolve(__dirname,"./"), entry:"../src/index.js" } //context是上个目录 module.exports = { context:path.resolve(__dirname,"../") entry:"./src/index.js" }
区分开发和生成环境配置
- 这里我们创建三个文件:
- webpack.comm.conf.js
- webpack.dev.conf.js
- webpack.prod.conf.js
coderwhy留下的题目,我在想要不要补充在这里。那就补充一点点好了
- webpack开发环境跟生产环境有什么区别?
开发环境-development |
生产环境-production |
|
模式(mode) |
在开发模式下,Webpack会更关注速度和开发体验,如输出的代码更容易阅读和调试 |
在生产模式下,Webpack会更关注文件大小和性能优化,如代码压缩和代码分离等 |
插件(plugins) |
在生产环境下,需要使用一些插件来对代码进行优化,如UglifyJsPlugin用于压缩代码,ExtractTextPlugin用于提取CSS文件等 |
|
输出文件(output) |
在开发环境下,Webpack通常会将所有的代码打包成一个或多个bundle.js文件 |
在生产环境下,Webpack通常会将不同的代码块(chunk)分开打包,以便于浏览器缓存和更好的加载性能 |
调试工具(devtool) |
在开发环境下,需要方便地调试代码,可以使用一些调试工具,如eval-source-map |
在生产环境下,可以使用一些轻量级的调试工具,如source-map |
- 总之,开发环境和生产环境在Webpack配置上的区别主要是在于性能和调试方面。开发环境更注重开发效率和调试方便,而生产环境更注重性能和文件大小优化