Vue框架
Vue3基础: 前端工程化,webpack,plugin、loader、Source Map
Vue框架是当前前端最火的框架,这里为了后期配合springBoot框架完成一个完整项目的搭建,之前已经分享过学习Vue的铺垫的知识比如ES6模块化,Promise,EventLoop事件循环[消息队列],宏任务和微任务;并且安装了Vue的工具node装载在HBuilderX中
Vue
对于Vue框架,我们首先就要了解前端工程化和webpack,webpack之前已经下载到了global中
前端工程化
之前没有接触前端的时候,或许很多人都觉得只要会Html + CSS + JavaScript就可以进行开发,利用bootStrap和JQuery就来美化页面和发送Ajax请求,利用art + template模板引擎来进行模板结构的渲染; 但是实际上 : 前端开发要遵守:
- 模块化 : js的模块化,css的模块化,其他资源的模块化
- 组件化: 复用现有的UI结构,样式,行为
- 规范化 : 目录结构划分,编码规范,接口规范,文档规范,Git分支管理
- 自动化 : 自动化构建,自动部署,自动化测试
前端工程化 : 企业级的前端项目开发中,把前端开发所使用的工具,技术,流程,经验等进行规范化、标准化、最终实现前面的几个标准
前端工程化能够让前端开发自成体系,覆盖前端项目从创建到部署的方方面面; 最大程度提高了前端的开发效率,降低了技术选型和前后端的协调沟通的成本
目前主流的解决方案就是webpack和parcel,这里主要简单介绍webpack
webpack
webpack介绍
webpack就是前端工程化的具体的解决方案
提供优化的前端工程化开发支持,代码压缩、处理浏览器端JavaScript的兼容性和性能优化;让工作重心放在功能的实现上,提高了可维护性【后端的Maven、Spring等都可以减少工作量】,项目大部分都是基于webpack进行打包构建
项目创建实例 : 列表隔行变色
- 新建项目,npm init -y 可以初始化包管理文件package.json - 这里直接在HBuilderX中新建一个空的项目webpack,然后运行命令npm init -y 使用ES6,所以要加上type : module
{
"name": "webpack",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="./index.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<ul>
<li>这是第1个li</li>
<li>这是第2个li</li>
<li>这是第3个li</li>
<li>这是第4个li</li>
<li>这是第5个li</li>
</ul>
</body>
</html>
-----------------使用npm命令引入jquery-------------------操作上面的dom
PS D:\HBuilderX\Web项目\webpack> npm i jquery -S
added 1 package in 2s
导入包之后,项目中用一个node_modules来存放下载导入的包,这样就可以使用默认导入在其他js文件中使用该目录下面的包【这样js脚本间就不需要像最初那样使用script标签来链入】
- 通过ES6模块化的方式导入JQuery,实现列表隔行变色
import $ from 'jquery'
$(function(){
$('li:odd').css('backgroundColor','red')
$('li:even').css('backgroundColor','green')
})
运行到浏览器会报错 : Uncaught SyntaxError: Cannot use import statement outside a module ;这是因为浏览器不兼容 ;而webpack就可以解决这些兼容性问题 — 自动将有兼容性问题的代码转化为没有兼容性的代码,然后运行到浏览器
给项目安装webpack使用命令安装两个包即可,只是开发时使用,所以是-D
npm i webpack@5.5.1 webpack-cli@4.2.0 -D
PS D:\HBuilderX\Web项目\webpack> npm i webpack@5.5.1 webpack-cli@4.2.0 -D
added 136 packages in 6s
项目中配置webpack
- 在项目的根目录中,创建名为webpack.config.js的webpack的配置文件
module.exports ={
mode: 'development'
}
- 在package.json的script【可运行脚本】中新增dev脚本 ; 使用
npm run XX 来运行脚本 ; npm run dev ; 这里的dev就是随意的,但是值就是webpack ;运行dev脚本就会启动webpack,然后读取webpack.config.js来读取配置项,对项目进行打包等处理
"scripts": {
"dev" : "webpack"
},
运行npm run dev之后,会生成dist目录,下面的main.js就是webpack解决之前index.js的兼容性后生成的新的js文件,重新引入
上面的test最好删掉,因为有的时候可能报错
//这里之前出现小问题
[webpack-cli] Error [ERR_REQUIRE_ESM]: require() of ES Module D:\HBuilderX\Web项目\webpack\webpack.config.js from D:\HBuilderX\Web项目\webpack\node_modules\webpack-cli\lib\groups\resolveConfig.js not supported.
这里是因为之前加入了type : module ; 这里要使用require(),这是CommonJS,所以要删掉
可以截取一小段main.js看一下
(() => {
__webpack_require__.n = (module) => {
var getter = module && module.__esModule ?
() => module['default'] :
() => module;
__webpack_require__.d(getter, { a: getter });
return getter;
};
})();
这里已经对所有的js文件进行了处理,并且使用了require,直接将这个文件链入index.html就可以解决兼容性问题
<script src="../dist/main.js" type="text/javascript" charset="utf-8"></script>
当修改js文件之后,如果没有热更新,就需要重新运行npm run dev命令,来执行webpack
module的可选值【webpack.config.js中】
webpack.config.js是webpack的配置文件,webpack在真正开始打包构建之后,会先读取这个配置文件,从而基于给定的配置,对项目进行打包; webpack是基于node.js开发的工具,所以配置文件,支持使用node.js的语法来进行个性化配置【CommonJS】
表示的是开发环境,不会对打包生成的文件进行代码压缩和性能优化, 所以打包的速度快, 适合在开发阶段使用
生产环境, 会对打包生成的文件进行代码压缩和性能优化, 所以打包速度要慢一点, 适合项目开发完成之后使用
webpack中默认的打包入口文件时src -> index.js
默认的输出文件路径为dist-> main.js
想要修改默认值,需要在webpack.config.js配置文件中进行配置,这里使用的node的语法CommonJS来引入path包: entry指代的时打包入口,output为打包的出口,path和filename分别指定出口的路径和名称
const path = require('path')
module.exports ={
mode: 'development',
entry: path.join(__dirname,'./src/index.js'),
output: {
path: path.join(__dirname,'./dist'),
filename: 'boundle.js'
}
}
使用的path.join进行路径的拼接 【 因为这里是相对路径】
前端相对路径/ ./ …/ …/…/
- 不加/就是资源路径,之前讲过,这里和 ./是相同的, ./和资源路径都表示相对路径是当前文件所在的目录路径
- / 是相对路径,如果是web项目,就是项目的路径之前的路径,就是端口号级,一般就是项目的上一级目录
- …/ 表示的是返回上一级目录,就是前文件所在目录的上一级目录为相对路径
- …/…/就是再上一级,依次类推
这里将之前的dist删除之后重新执行命令,发现修改成功
webpack中的plugin
上面每次修改代码之后,都要重新运行npm run dev来执行webpack,可以使用plugin来进行热更新,通过安装和配置第三方的插件,可以拓展webpack的能力
-
webpack-dev-server
-
类似于node.js中的命令nodemon,热更新; 每当修改了源代码,webpack会自动对项目进行打包和构建 -
【-D代表将其记录到开发结点下】,运行命令npm i webpack-dev-server@3.11.0 -D , 下载之后就需要配置到项目中 -
配置 : 修改package.json-> scripts中的dev命令,之前是webpack,直接执行并不会进行热更新 "dev": "webpack serve"
---------------------result-----------------------
PS D:\HBuilderX\Web项目\webpack> npm run dev
> webpack@1.0.0 dev
> webpack serve
(node:552) [DEP0111] DeprecationWarning: Access to process.binding('http_parser') is deprecated.
(Use `node --trace-deprecation ...` to show where the warning was created)
× 「wds」: Error: listen EACCES: permission denied 127.0.0.1:8080 ---- netstat杀死即可
at Server.setupListenHandle [as _listen2] (node:net:1313:21)
at listenInCluster (node:net:1378:12)
at GetAddrInfoReqWrap.doListen [as callback] (node:net:1516:7)
at GetAddrInfoReqWrap.onlookup [as oncomplete] (node:dns:73:8) {
code: 'EACCES',
errno: -4092,
syscall: 'listen',
address: '127.0.0.1',
port: 8080
}
需要注意的是: webpack-server会启动一批个实时打包的http服务器,所以查看打包效果在http://localhost:8080; 这里和之前的nodemon挂载服务器是一样的效果; 这里可能存在端口号被占用的情况,这里可以先关掉 打开这个网址之后,出现的是项目的目录结构,包括dist等,所以点击src就可以运行index.html; 但是当直接进行修改之后,浏览器中并没有马上改变,这是由于配置插件后打包的文件是到缓存中 打包文件的去向
- 在不配置webpack-dev-server的情况下,webpack打包生成的文件直接放到物理磁盘上【严格遵守在webpack.config.js中的配置,output结点的指定路径】
- 配置之后,打包生成的文件存放到内存中 【不再放到磁盘中,提高实时打包输出的性能,因为内存的速度更快】
webpack-dev-server生成到内存中的文件,默认放到项目的根目录中,并且是虚拟的,不可见的 , 可以8080/bundle.js查看到一个文件
<script src="/boundle.js" type="text/javascript" charset="utf-8"></script>
这样保存就会自动更新页面nodemon
-
html-webpack-plugin webpack中的HTML插件,类似于一个模板引擎插件; 可以通过此插件自定制index.html的内容 安装 : 使用命令npm i html-webpack-plugin -D 这样就可以直接安装到最新的版本 配置 : 打开webpack.config.js
const HtmlPlugin = require('html-webpack-plugin')
const htmlPlugin = new HtmlPlugin({
template: './src/index.html',
filename: './idex.html'
})
plugins: [htmlPlugin]
实例 :通过html-webpack-plugin插件,将src下面的index.html首页复制一份到根目录中,通过template和filename就可以 将index.html复制一份到根目录下【浏览器内存】 HTML插件复制到根目录的idex.html页面,放入的是内存; 并且页面的底部自动注入了打包的bundle.js文件, < script defer src=“boundle.js”>< /script>所以就不需要再手动注入了 开启实时打包之后,加入html插件,可以删除dist目录,因为不再依赖其下面的bundle.js文件了,而是临时的根目录中的虚拟文件
【通过按两次CTRL + C就可以结束nodemon命令,cls命令可以清屏】 -
devserver结点 在webpack.config.js配置文件中,可以通过devServer结点对webpack-dev-server插件进行更多的配置,open指定是否自动打开,host和port指定端口号; 配置结点和之前的module,output,entry,plugins平级 devServer:{
open: true,
host: '127.0.0.1',
port:8090
}
这里的设置和之前的ES6实例中的nodemon配置服务器相同; 这里需要重新配置服务器
webpack中的loader
在实际的开发中,webpack默认只能打包处理.js后缀名的模块,其他的非.js结尾的模块如.css不能处理,这个时候,就要使用loader加载器来进行打包
loader加载器的作用 : 协助webpack打包处理指定的文件模块
- css-loader : 可以打包处理.css相关的文件
- less-loader : 可以打包处理.less相关的文件
- babel-loader : 可以打包处理webpack无法处理的高级JS语法
loader的调用过程:
先判断待处理的模块,如果为js,判断是否有高级的JS语法,没有就直接打包处理,否则就判断是否安装配置相关的loader
在webpack中,一切皆模块; 所以js中可以导入任何的模块比如css等
打包css文件
这里可以继续操作上面的index.html,为其加上样式,在src目录下再创建css文件夹,
其中的index.html 【去掉列表前面的*】
ul:{ ----> 这是错误的写法,选择器后面应该直接跟{},加上: 在firefox中会警告
list-style: none;
}
--------------直接就是选择器加上{样式}---------------
ul{
list-style: none;
}
要让这个css文件生效,按照之前,就会link链入,现在按照模块化思维,直接导入到index.js中即可
import './css/index.css'
- 安装加载器style-loader,css-loader,直接运行命令 :
npm i style-loader css-loader -D - 配置 : 在webpack.config.js中的modlue -> rules数组中,添加loader规则,test和use分别指定后缀名和其加载器; style-loader在css-loader之前
const path = require('path')
const HtmlPlugin = require('html-webpack-plugin')
const htmlPlugin = new HtmlPlugin({
template: './src/index.html',
filename: './index.html'
})
module.exports ={
mode: 'development',
entry: path.join(__dirname,'./src/index.js'),
output: {
path: path.join(__dirname,'./dist'),
filename: 'boundle.js'
},
plugins: [htmlPlugin],
devServer:{
open: true,
host: '127.0.0.1',
port:8090
},
module:{
rules:[
{test:/\.css/,use:['style.loader','css.loader']}
]
}
}
重启服务器,运行即可打包
Can’t resolve ‘style.loader’ 问题
这里是因为我们安装了高版本的webpack,所以配置的语法已经不是之前的,在webpack4.xx以后,配置loader必须要用对象的方式指明loader,即 use:[{loader:xxx},……]
module:{
rules:[
{ test: /\.css/, use: [{ loader: 'style-loader' }, { loader: 'css-loader' }] }
]
}
这里就是要注意,loader前面必须加上loader:
打包处理less文件
less文件可以操作margin和padding等位置,所以这里就美化一下之前的列表,在css下面新建一个index.less文件
html,body,ul{
margin: 0;
padding: 0;
li{
line-height: 35px;
padding-left: 10px;
font-size: 12px;
}
}
之后在index.js中导入这个模块 import ‘./css/index.less’,要想打包处理,还是需要安装配置两个loader
安装 : npm i less-loader less -D
配置 : { test: /.less$/,use: [{ loader: ‘style-loader’ }, { loader: ‘css-loader’ },{loader:‘less-loader’}]}//不用less,less是less-loader的内置依赖项,而是要用style和css
打包处理样式表中与url相关的文件 url-loader file-loader
现在在index上面新建一个id为box的div,目的是将src/img/local.png作为该box的背景图片
正常来说,在index.less下面,会对这个div进行样式的编辑
#box{
width: 380px;
height: 114px;
background-color: yellow;
background: url(../img/local.png);
}
保存之后,也还是报错了: You may need an appropriate loader to handle this file type, 这是因为不能处理图片文件.jpg,.png结尾的文件
安装: npm i url-loader file-loader -D 安装两个loader
配置 : { test: /\.jpg|png|gif$/,use:[{loader: 'url-loader'}]} //暂时就只配置url-loader,图片各种后缀使用|
之后重新运行即可:但是div的背景是截取的图片的一部分…
url-loader参数limit
网页中,小的图片可以直接转化为base64直接加载,大型图片再发请求,这样可以提高网页访问的性能,而选择大小就需要url-loader的参数limit ,小于等于的就会转为base64,limit是用来指定图片的大小,单位为byte
{ test: /\.jpg|png|gif$/,use:[{loader: 'url-loader?limit=207946'}]
设置之后可以重新查看图片 : url(data:image/png;base64 —> 被转为了base64
loader配置其他方式
loader配置可以采用对象的方式进行配置:
use:{
loader:'url-loader' ,
options:{
limit:2229
}
}
打包处理js文件高级语法
webpack只能打包处理一部分高级的js语法,对于webpack无法处理的js高级语法,只能使用babel-loader来协助打包;最新版本的webpack可以处理
class Person{
static info = 'person info';
}
babel-loader含有三个主要的包babel-loader,@babel/core,@babel/plugin-proposal-class-properties
安装 : npm i babel-loader @babel/core @babel/plugin-proposal-class-properties -D
配置 : 需要注意,除了test和use,还有一个exclude : 排除项 :‘node_modules’;babel-loader只需要处理用户编写的js文件,不需要处理node_modules下面的下载的其他的包文件,这样速度快
{
test: /\.js$/,
exclude:/node_modules/ ,
use:{
loader: 'babel-loader',
options:{
plugins:['@babel/plugin-proposal-class-properties']
}
}
}
上面的都是rules数组的一项
打包发布
项目完成之后,使用webpack对项目进行打包发布 :
- 开发环境下,打包生成的文件存放再内存中,无法获取到最终生成的文件
- 开发环境下,mode为development,不会对代码进行压缩和性能优化,所以需要打包发布
配置webpack的打包发布
之前再package.json下面的scripts结点下配置的是dev命令,代表的就是development,当项目完成之后,重新配置命令build
'build': 'webpack --mode production'
这里会覆盖config中的mode的值
这样使用命令npm run build
生成文件位置统一
直接生成文件杂乱,要将js文件统一生成到js目录中,需要再output中进行配置
output: {
path: path.join(__dirname,'./dist'),
filename: 'js/boundle.js'
}
对于图片文件,生成到img目录下,需要对url-loader进行配置,除了原来的limit参数,新增一个outputPath参数指定路径
{ test: /\.jpg|png|gif$/,use:{
loader: 'url-loader',
options:{
limit:227946,
outputPath:'image'
}
}}
自动清理dist目录
为了每次打包发布自动清理dist目录,安装配置插件clean-webpack-plugin npm i XX -D
安装配置这个插件和之前配置html插件是相同的
const {CleanWebpackPlugin} = require('clean-webpack-plugin')
const cleanPlugin = new CleanWebpackPlugin()
const HtmlPlugin = require('html-webpack-plugin')
const htmlPlugin = new HtmlPlugin({
template: './src/index.html',
filename: './index.html'
})
module.exports ={
mode: 'development',
entry: path.join(__dirname,'./src/index.js'),
output: {
path: path.join(__dirname,'./dist'),
filename: 'js/boundle.js'
},
plugins: [htmlPlugin,cleanPlugin],
在高级的打包发布中,包括打包生成报告,分析具体的优化法案,Tree-Shaking,为第三方库提供CDN加载,配置组件的按需加载,开启路由懒加载,自定制首页的内容
Source Map
生产环境中遇到的问题: 前端项目投入生产环境后,都需要对js文件进行压缩混淆,从而减小体积,提高加载效率,但是产生问题 : 压缩后的代码不好debug
Source Map是一个信息文件,里面存储这位置信息, 存储代码压缩前后的位置的对应关系,有了Source Map,出错的时候,出错工具直接显示的源代码,而不是转换后的代码,方便后期的调试
在开发环境下,webpack默认开启了Source Map功能,出错的时候,控制台显示的错误行的位置,定位具体的源代码,但是默认的有一定的问题,默认的是生产后的代码的位置,行数不一致
在webpack-config.js文件中加入配置,就是和model平级
module.exports ={
mode: 'development',
devtool: 'eval-source-map', -----------------------------------------增加的配置
entry: path.join(__dirname,'./src/index.js'),
output: {
path: path.join(__dirname,'./dist'),
filename: 'js/boundle.js'
},
plugins: [htmlPlugin,cleanPlugin],
devServer:{
open: true,
host: '127.0.0.1',
port:8090
},
module:{
rules
配置之后,行数就是前后一致的
生产环境下的Source Map
在生产环境下,省略devtool选项,最终生成的文件不包含Source Map,这就可以防止原始代码通过Source Map泄露,这样定位的错位都是转化的混淆的代码,对调试不好可以设置为: 只显示行数,不暴露代码
devtool: 'nosources-source-map'
这样既方便调试,也不会泄露代码
但是devtool : ‘source-map’ 就是可以定位到源码,和之前的开发环境的eval-source-map的效果相同,十分不安全,一般就用nosources或者直接关闭🎄
|