Webpack详解(二)

本文涉及的产品
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
简介: Webpack详解

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

会将DefinePlugin

process.env.NODE_ENV

的值设置位development

为模块(分包的)和chunk启用有效的名(能让你看懂的名字)

production

会将DefinePlugin

process.env.NODE_ENV

的值设置位production

。为模块和chunk启用确定性的混淆名称,FlagDependencyUsagePlugin

FlagIncludedChunksPlugin

ModuleConcatenationPlugin

NoEmitOnErrorsPlugin

TerserPlugin(代码压缩的)

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是怎么搭建本地服务器的:


  1. 不再对dits文件做单独的打包,因为webpack搭建出来的本地服务器能够自动的对src(也就是我们写的代码)进行打包,打包后不会生成对应的本地文件的(因为生成本地文件还需要写入本地文件外加读取本地文件,效率太低)。
  2. 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配置上的区别主要是在于性能和调试方面。开发环境更注重开发效率和调试方便,而生产环境更注重性能和文件大小优化
目录
相关文章
|
26天前
|
移动开发 JSON JavaScript
一文带你了解和使用webpack(2024年11月)
欢迎来到我的博客!我是瑞雨溪,一名热爱JavaScript和Vue的大一学生。自学前端已有两年半的时间,目前正努力向全栈开发迈进。如果你在我的博客中有所收获,欢迎关注我,我会持续更新更多优质内容。你的支持是我最大的动力!🎉🎉🎉
28 1
一文带你了解和使用webpack(2024年11月)
|
3月前
|
JavaScript 前端开发
webpack快速使用
webpack快速使用
173 63
|
7月前
|
前端开发 JavaScript
webpack使用
webpack使用
|
7月前
|
前端开发 JavaScript Linux
|
JavaScript 前端开发
webpack
webpack
59 0
webpack
|
7月前
|
前端开发 JavaScript 测试技术
对Webpack的理解
对Webpack的理解
48 0
|
JSON 缓存 前端开发
webpack相关详细讲解。
webpack相关详细讲解。
|
缓存 前端开发 JavaScript
浅谈webpack
浅谈webpack
106 0
|
JavaScript 前端开发
从了解到使用webpack
Webpack本质上是一种前端资源编译,打包工具
109 0
|
前端开发 JavaScript
关于 Webpack 的介绍,什么是 Webpack?
Webpack 是一款现代化的前端构建工具,它可以将你的项目中的多个 JavaScript 模块打包成一个或多个 bundle 文件,同时还可以处理各种类型的静态资源,比如 CSS、图片等等。 Webpack 最初是由 Tobias Koppers 开发的,目前已经成为了前端开发中使用最广泛的构建工具之一。
159 0