
【项目总结文档】Vue全家桶开发电商管理系统项目
引言
这个项目是我第二次做了,第一次做的时候好多地方不是很懂,而现在学习了基础知识后,回过来再做一次,发现原来不是很懂的地方也弄明白了,然后又在B站找了项目实战撸了一把,想通过这篇文章,对其中的模块实现做一下总结,同时希望能够加深对项目的理解,不断发掘其中的亮点。如果你觉得本文还行,请毫不留情的点赞!
element-ui篇
el-form 组件问题
el-form
组件默认是 content-box
,我们设置其如下属性时,就会出现长度比我们想象中长一点的情况。
1 | .login_form{ |
解决办法如下,直接设置 box-sizing
为 border-box
即可。
1 | .login_form{ |
使用 iconfont 给输入框添加图标
在 main.js
中导入字体图标
然后在 el-input
组件中通过 prefix-icon
进行相关图标引用
最终效果图如下:
如何进行表单验证
Form
组件提供了表单验证的功能,只需要通过 rules
属性传入约定的验证规则,并将 Form-Item
的 prop
属性设置为需校验的字段名即可。
通过 rules
属性传入约定的验证规则
将Form-Item
的 prop
属性设置为需校验的字段名
如何重置表单
element-ui
对表单提供了如下方法 resetFields
,我们只需要获取表单对象数据即可重置我们的表单。
获取表单对象方式如下:
直接在表单处添加 ref
属性,如下 loginFormRef
,此引用即为我们表单实例。
然后,在我们重置按钮处,通过 @click
给按钮绑定一个事件
下一步,添加方法,我们可以打印一下 this
不难发现,此时的 this
指向的就是我们当前登录组件 login.vue
的实例对象。
观察上图,我们看到有一个 $refs
属性,这个就是我们的表单实例。
此时,我们的方法就可以改写成如下方式:
最后,我们点击重置按钮后,会发现输入框并不是完全清空了,原因是data数据里面一开始我们设置了默认值,因此resetFields()函数就是清空为默认值。
登录预校验
在我们点击登录按钮,不应该直接发起网络请求,而是应该对表单进行预校验,检验成功才会发送请求。
拿到表单引用对象,即可进行对表单的校验。
首先,给登录按钮通过 @click
来绑定一个事件
下一步,在 methods
中添加 login
方法,validate
函数参数为一个回调函数。该回调函数会在校验结束后被调用,并传入两个参数:是否校验成功和未通过校验的字段。若不传入回调函数,则会返回一个 promise
此时,我们点击登录按钮,查看是否进行了预校验:
此时,按照之前的校验规则,是存在问题的。所以返回 false
。我们来一个正确示例吧:
配置弹框提示组件
首先,在 element.js
中导入弹框提示组件,但是它的配置与其它组件不一样,它需要进行全局挂载。
全局导入后,我们就可以在我们的登录组件 login.vue
中通过 this
来访问弹框提示组件了。
测试一下,输入 admin
和 123456
,此时就会提示输入成功。
每一个组件都是一个类名
每一个组件都是一个类名,我们可以直接增加效果属性。
el-menu 默认会有一个 border-right
这样会导致我们的菜单栏右边会有一个若隐若现的线条凸起
解决办法如下,直接将 el-menu
的border-right
设置为 none
即可。
表格展开页
只需要将 el-table-column
中 type
属性设为 expand
即能将表格进行展开。
实现效果如下:
使用树形控件 el-tree
对于分配权限一栏,我们需要如下效果:
相关配置属性:
其中 data
为我们的数据源,props
为我们在 tree
组件显示的文本内容。通过设置 node-key
可以让每个树节点作为唯一标识的属性,整棵树是唯一的;通过设置 default-expand-all
来默认展开我们的所有节点,不需要每次都让用户去打开,体验感好;通过设置 default-checked-keys
勾选我们已有的权限。
最后,我们通过递归的方式,判断当前 node
节点是否存在 children
属性,如果不存在的话,就包含了三级权限,然后添加到我们的数组中,然后通过 :default-checked-keys="defKeys"
来渲染选中当前已有的权限。
此外,当我们关闭对话框时还需要监听一下关闭事件,不然每次数组都会保存原来的权限数据,导致一些问题。因此,监听 close
事件后,每次对话框关闭时,都将数组进行清空。
获取选中节点的keys:
首先,给我们对话框的确定按钮绑定一个事件。
主要使用 tree
组件提供的两个方法 getCheckedKeys
和 getHalfCheckedKeys
来分别返回目前被选中的节点的 key
所组成的数组和目前半选中的节点的 key
所组成的数组
使用动态编辑标签
实现效果如下:
通过 v-if
的 boolean
值来动态变化是否显示文本框还是 button
按钮。通过 v-model
双向绑定来实现文本框内容的监听。
由于每一行需要设置文本框的显示与隐藏,而且数据是共享的。我们需要通过 scope
来获取每一行的值来进行绑定,不然的话,就会导致某个文本框显示了,其它文本框也跟着显示,并且数据是共用的,都会同步变化。而设置 scope
后,我们就能实现对一行数据进行更新渲染了。
为了实现当我们点击按钮后,让本文看自动获取焦点。
通过 this.$refs.saveTagInput.$refs.input.focus()
来获取 input
的 dom
对象,接着调用 focus
函数来获取焦点。
$nextTick
作用是当页面元素被重新渲染之后才会执行回调函数中的代码。如果不这样做的话,我们直接通过点击按钮的形式,将该行的 inputVisible
设置为了 true
,那么此时直接调用 this.$refs.saveTagInput.$refs.input.focus()
是没办法获取焦点的,此时就会报错。因为我们的 dom
节点还没有进行渲染,而先调用 $nextTick
就是为了等待 dom
节点渲染之后,我们再获取 input
,然后再调用 focus
函数来获取焦点。
步骤条的使用与美化
以下就是步骤条使用的核心代码,其中 active
绑定的是每一个 step
的下标,默认从 0
开始。其次,我们可以设置 aligin-center
属性来让我们的步骤条进行居中。el-step
就是每一个步骤进度。
1 | <!-- 步骤条区域 --> |
更改原本样式,得到我们想要的效果:
1 | .el-steps{ |
最终实现效果如下:
阻止页签tabs切换
主要函数如下:
在我们的 tabs
标签页添加一个 before-leave
函数
然后在 methods
中定义,根据第一个标签页的逻辑来阻止标签页的切换。
Upload 上传组件
通过点击或者拖拽上传文件
1 | <!-- action表示图片上传后台api地址 --> |
配置如下之后,并不代表就真正上传了,此时,我们打开 Network
查看 Preview
,发现 msg
提示我们 无效 token
,状态码为 400
,这代表并没有上传成功。
这是因为此时上传控件没有使用 axios
发 ajax
请求,而是组件内部自动封装了一个 ajax
,因此也就不会调用下述请求拦截器了。
解决办法是 Upload
组件有一个 headers
属性,可以设置上传的请求头部。
第一步,在组件处添加 headers
属性
第二步,在 data
中定义 headersObj
,然后添加请求头对象。
操作完成后,可以看到提示消息 msg
显示上传成功,并且此时状态码也变为了 200
。
监听图片上传成功事件
监听图片删除事件
1 | // 处理图片移除的操作 |
处理图片预览操作
图片预览窗可以用 el-dialog
组件来做,然后通过 on-preview
函数来处理图片预览的操作。
1 | <!-- 图片预览 --> |
通过函数来获取上传图片的真实 url
,然后监听图片预览窗口的打开即可。
1 | // 处理图片预览的操作 |
最终效果如下:
使用Timeline 时间线
可视化地呈现时间流信息。
由于 vue-cli-plugin-element
最后更新时间是 2019年1月
,而 element-ui
中 Timeline 时间线
更新是在 3月份
,因此我们没有办法直接进行引用。因此,我们直接通过手动导入的方式。
然后,我们打开 element.js
,进行导入
1 | import Timeline from './timeline/index' |
同时,我们也需要导入我们的 css
样式
1 | <style lang="less" scoped> |
1 | <!-- 展示物流进度的对话框 --> |
最终实现效果:
Vue篇
如何导入全局样式表
直接在 main.js
将相关样式导入即可
1 | // 导入全局样式表 |
如何重定向路由
在 router
配置页中使用 redirect
属性
element-ui 如何按需导入
在element.js
文件中,按照如下方式,进行按需导入即可。然后通过 Vue.use()
方法进行引用。(优化点:也就是将组建导入都放在一起,如果组件过多的话,支持换行)
配置axios
在 main.js
文件内进行配置
那么,此时我们就可以通过 this
访问登录组件原型上 $http
方法,来发起对后端的请求了。
保存token
将登录成功之后的 token
,保存到客户端的 sessionStorage
中
- 项目中除了登录之外的其它
api
接口,必须在登录之后才能访问 token
只应在当前网站打开期间生效,所以将token
保存在sessionStorage
中
通过编程式导航跳转到后台主页,路由地址是 /home
在我们进行登录请求时,我们不妨打印一下,请求过来的数据,如下,服务端那边会传过来一个 token
值。
下一步,我们在登录成功后,将服务端返回过来的 token
值直接种植到 sessionStorage
中,然后通过编程式导航跳转到后台主页(/home
),通过 $router.push()
方法即可。
此时,我们打开浏览器 ,通过F12
查看Application
属性,找到 sessionStorage
即可查看到我们刚刚种植的 token
值了。
路由导航守卫控制访问权限
如果用户没有登录,但是直接通过URL访问特定页面,需要重新导航到登录页面。
在之前的操作中,我们登录之后会种植一个 token
值,表示我们登录成功了,那么此时我们将 token
值去掉呢?
直接点击上述 clear all
按钮去掉之后,我们依旧是可以访问 /home
的路由,没有登录也能访问我们的后台主页,这肯定不是我们想要的结果。
在 router/index.js
中进行相关配置,具体如下,调用路由实例 router
的 beforeEach
方法,即可挂载我们的路由导航守卫。
这里可能会有疑问,我们需要验证 token的正确性吗?
答案是不需要,因为前端只需要管要不要给用户呈现这个页面,而我们调用api时,后端会对我们的 token 值进行校验,前端不需要验证。
退出功能
基于 token 的方式实现退出比较简单,只需要销毁本地的 token 即可。这样,后续的请求就不会携带 token ,必须重新登录生成一个新的 token 之后才可以访问页面。
那么,我们仅需要为退出按钮绑定一个事件即可。
然后事件内容就是:先清空 token
,然后跳转到我们的登录页面。
核心代码如下:
JSON格式的配置文件
在项目根目录创建名为 .prettierrc
的文件,增加如下代码:
1 | { |
semi
设置 false
去掉分号,singleQuote
设置 true
使用单引号。
此外,还可以禁用 function
处空格报错,增加如下代码:
1 | 'space-before-function-paren': 0 |
通过axios请求拦截器添加 token
通过axios请求拦截器添加 token,保证拥有获取数据的权限。
原因是,后台那边除开登录的 api
,其它都需要进行授权。
因此,我们可以利用 axios
中interceptors
属性,其中有一个成员 request
,此时我们可以通过 use
函数为请求拦截器挂载一个回调函数,只要向服务器端发送了一个 axios
请求,会优先调用 use
函数。
首先,在 main.js
添加如下代码:
此时,打印 config
,查看结果如下,发现我们headers
字段并没有一些授权字段。
此时,我们添加如下一行代码,通过 token
来进行授权。
此时,在Network
就能查看到有一个 Authorization
字段了,但这里是为 null
,因为我们进行的是登录请求,在登录期间,服务器是不会颁发令牌(token
)。如果登录之后,调用其它 api
接口的话,就会颁发相应的token
令牌。
左侧菜单栏
关于这一块的话,由于后台数据已经写好,我们只需要通过双层 for
循环即可渲染我们的菜单栏,注意点:
:index
只能绑定字符串,因此将后台请求过来的 id
值与空字符串进行拼接达到此效果,解决了点击某个菜单栏导致其它菜单栏同时打开的问题。
最终实现效果如下:
左侧菜单栏图标设计
我们想要的效果如下:
如何设计?
首先,我们可以在 data
中定义一个对象,对应于每一个菜单选项的 id
然后通过 for
循环遍历每一个菜单选项的 id
即可。
保持一个子菜单的展开
直接在侧边栏区域添加上述属性即可
让菜单栏展开与折叠
通过点击一个按钮,让侧边栏进行展开与折叠。通过 isCollapse 的值来动态变化侧边栏的宽度。
其中 cursor: pointer 设置是为了让鼠标放在折叠与展开处会有一个手指指向。
letter-spacing: 0.2em 是为了让 ||| 有一定间隔
实现首页路由重定向
我们想要在登录之后重定向到 /welcome
路径,于是需要添加子路由children
属性,然后设置 redirect
重定向到我们的子路由。
然后在我们组件 Home.vue
的右侧主体区域,放置一个路由占位符 router-view
即可。
侧边栏路由改造
通过给侧边栏设置 router
属性为 true
,我们就能开启 vue-router
路由模式,然后将我们二级菜单的 index
属性绑定我们的数据 path
即可。
在sessionStorage保存左侧菜单栏的激活状态
为了让我们点击二级菜单时,会有一个激活效果,而且是保持状态,我们需要将利用 element-ui 菜单栏相关
default-active
属性,来让菜单保持激活。
由于每个二级菜单都有一个路由链接,不妨将路由路径 path
存储在 sessionStorage
中,具体做法就是给二级菜单绑定一个事件:
每次触发点击事件,我们需要更新当前路由路径,才能让点击的那个按钮高亮。
然后在我们创建这个组件时,就获取当前的激活状态的路径即可。
查看 sessionStorage
,可以看到我们存储的路由路径。
slot插槽使用
项目需求:由于用户列表状态后台返回的是 true/false,无法进行渲染,而我们需要的是有一个Switch开关来控制我们的状态。添加一个
template
模板后,此时就可以用slot-scope
作用域插槽来获取我们数据列表中的每一行数据,具体如下:
最后,我们就可以得到如下效果图了:
通过switch开关更改用户状态
首先,在 switch
开关添加一个 change
事件,并且通过作用域插槽的形式,将该行数据作为参数传入,目的是为了后续的修改。
在函数内我们将传递过来的参数作为我们请求的参数,通过 put
方式修改我们的后台数据。
input输入框优化
通过增加 clearable
属性,我们的输入框就可以多一个 x
,然后通过绑定 clear
事件,当我们进行清除 (即点击由 clearable
属性生成的清空按钮时触发)时,就会重新获取我们的用户列表,不再需要用户再次点击搜索按钮去获取了。
正则表达式验证邮箱和手机号码
1 | // 验证邮箱的规则 |
使用vue-table-with-tree-grid
安装新的依赖 vue-tabel-with-tree-grid
vue-tabel-with-tree-grid 官方文档
安装完成后,在 main.js
入口文件内先导入 tree-tabel
然后全局注册组件 tree-tabel
页面中,我们使用了如下属性:
data
确定我们的数据源,columns
定义我们的指定列,selection-type
设置是否打开多选框,expand-type
设置是否展示展开栏,show-index
添加索引列, border
给表格添加边框。
使用模板列:
通过在columns
设置 type
属性值为 template
,即可设置模板列。
然后在我们界面表格区域,添加一个 template
模板,然后设置作用域插槽 slot
为在数据块定义的模板名称 isOk
自定义格式化时间的全局过滤器
在 main.js
入口文件全局注册格式化时间的过滤器,代码如下所示:
1 | // 自定义格式化时间的全局过滤器 |
在我们的组件当中,通过 |
来给我们的时间添加一个过滤器
最终实现效果如下图所示:
添加富文本编辑器
通过 vue-ui
界面,可以安装我们所需要的依赖,或者使用下文 npm
或 yarn
安装。
NPM
1 | npm install vue-quill-editor --save |
Mount with global
1 | import Vue from 'vue' |
打开 main.js
入口文件,进行全局导入和注册:
1 | // 导入富文本编辑器 |
使用
通过 quill-editor
标签,然后通过 v-model
双向绑定到 form
表单的商品详情描述变量 goods_introduce
上。
最终实现效果如下:
使用 lodash 中 cloneDeep(obj) 来实现深拷贝
Using npm
1 | $ npm i -g npm |
_.cloneDeep(value) 使用
项目中使用 cloneDeep
需求:由于 addForm
中商品所属的分类数组 goods_cat
在商品分类模块需要使用 v-model
进行双向绑定数组形式,而我们调用添加商品 api
时,需要字符串形式的,这就产生了冲突,于是我们可以通过深拷贝操作来达到我们的需要。
首先,导入 lodash
。
然后,直接调用 lodash
中 cloneDeep
方法实现对对象的深拷贝。
使用 echarts
echarts 官方文档传送门
根据官方文档示例,我们先展示测试数据。
1 | <template> |
最终实现效果:
由于通过 $http
获取得到的数据缺少鼠标跟随的效果,于是需要将 options
进行合并操作,此时使用了 lodash
的 merge
函数。核心代码如下:
1 | // 4.准备数据和配置项(res.data) |
在此提供数据报表折线图绘制的源代码:
1 | <template> |
最终实现效果如下:
项目优化上线
优化Vue项目,部署Vue项目
项目优化
添加进度条
打开 vue-ui
面板,选择依赖,输入 nprogress
进行安装相关依赖。
npm
1 | npm install --save nprogress |
在 main.js
入口文件中,进行相关配置。首先先导入包对应的js
和 css
:
1 | // 导入NProgress包对应的js和css |
配置 request
请求拦截器 和 response
响应拦截器,这样我们就能在每次网络请求时能够展示进度条了。
1 | // 在 request 拦截器中,显示进度条 NProgress.start() |
执行build 时报错
Error: No module factory available for dependency type: CssDependency
解决办法:
参考:解决webpack打包报错 No module factory available for dependency type: CssDependency
在执行 build
命令期间移除所有的 console
babel-plugin-transform-remove-console 官方文档传送门
可以通过 vue-ui
面板,选择开发依赖,然后输入 babel-plugin-transform-remove-console
进行安装
npm
1 | npm install babel-plugin-transform-remove-console --save-dev |
安装依赖之后,打开 babel.config.js
文件,在 plugins
插件处,添加一个字符串,'transform-remove-console'
,如下图所示位置。
1 | module.exports = { |
上述设置好了之后,还存在一个问题,我们只需要在发布阶段才会去除 console
,在开发和测试环境下如果去除了 console
,对于我们调试方面不太好。因此,我们需要设置只在生产环境下去除 console
。
通过上下两个图比较,我们可以发现,在开发环境下 mode
值为 development
,而在生产环境下mode
值为 production
。
因此,上述代码就需要进行些微修改,如下所示:
1 | // 项目发布阶段需要用到的 babel 插件 |
生成打包报告
打包时,为了直观地发现项目中存在的问题,可以在打包时生成报告。生成报告的方式有两种:
① 通过命令行参数的形式生成报告
1 | // 通过 vue-cli 的命令选项可以生成打包报告 |
② 通过可视化的UI面板直接查看报告(推荐)
在可视化的UI面板中,通过控制台和分析面板,可以方便地看到项目中所存在的问题。
通过 vue.config.js 修改 webpack 的默认配置
通过 vue-cli 3.0
工具生成的项目,默认隐藏了所有 webpack 的配置项,目的是为了屏蔽项目的配置过程,让程
序员把工作的重心,放到具体功能和业务逻辑的实现上。
如果程序员有修改 webpack 默认配置的需求,可以在项目根目录中,按需创建 vue.config.js
这个配置文件,从
而对项目的打包发布过程做自定义的配置
(具体配置参考https://cli.vuejs.org/zh/config/#vue-config-js)。
1 | // vue.config.js |
为开发模式与发布模式指定不同的打包入口
默认情况下,Vue项目的开发模式与发布模式,共用同一个打包的入口文件(即 src/main.js
)。为了将项目
的开发过程与发布过程分离,我们可以为两种模式,各自指定打包的入口文件,即:
- 开发模式的入口文件为
src/main-dev.js
- 发布模式的入口文件为
src/main-prod.js
configureWebpack
和 chainWebpack
在 vue.config.js
导出的配置对象中,新增 configureWebpack
或chainWebpack
节点,来自定义 webpack
的打包配置。
在这里, configureWebpack
和 chainWebpack
的作用相同,唯一的区别就是它们修改 webpack 配置的方式不同:
① chainWebpack
通过链式编程的形式,来修改默认的 webpack
配置
② configureWebpack
通过操作对象的形式,来修改默认的 webpack
配置
两者具体的使用差异,可参考如下网址:
通过 chainWebpack 自定义打包入口
示例代码如下:
1 | module.exports = { |
第三方库使用CDN
通过 externals 加载外部 CDN 资源
默认情况下,通过 import
语法导入的第三方依赖包,最终会被打包合并到同一个文件中,从而导致打包成功后,单文件体积过大的问题。
例如上述 chunk-vendors.js
体积很大,原因是全部 import
所依赖的包进行了合并给它。
为了解决上述问题,可以通过 webpack
的 externals
节点,来配置并加载外部的 CDN
资源。凡是声明在externals
中的第三方依赖包,都不会被打包。
具体配置代码如下:
1 | config.set('externals', { |
同时,需要在 public/index.html
文件的头部,添加如下的 CDN
资源引用:
1 | <!-- nprogress 的样式表文件 --> |
同时,需要在 public/index.html
文件的头部,添加如下的 CDN
资源引用:
1 | <script src="https://cdn.staticfile.org/vue/2.5.22/vue.min.js"></script> |
Element-UI 组件按需加载
通过 CDN 优化 ElementUI 的打包
虽然在开发阶段,我们启用了 element-ui 组件的按需加载,尽可能的减少了打包的体积,但是那些被按需加载的组件,还是占用了较大的文件体积。此时,我们可以将 element-ui
中的组件,也通过 CDN
的形式来加载,这样能够进一步减小打包后的文件体积。
具体操作流程如下:
① 在 main-prod.js
中,注释掉 element-ui
按需加载的代码
② 在 public/index.html
的头部区域中,通过 CDN
加载 element-ui
的 js
和 css
样式
1 | <!-- element-ui 的样式表文件 --> |
首页内容定制
不同的打包环境下,首页内容可能会有所不同。我们可以通过插件的方式进行定制,插件配置如下:
1 | chainWebpack: config => { |
在 public/index.html
首页中,可以根据 isProd
的值,来决定如何渲染页面结构:
1 | <!–- 按需渲染页面的标题 --> |
路由懒加载
当打包构建项目时,JavaScript
包会变得非常大,影响页面加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了。
具体需要 3 步:
- 安装
@babel/plugin-syntax-dynamic-import
包。 - 在
babel.config.js
配置文件中声明该插件。 - 将路由改为按需加载的形式,示例代码如下:
1 | // /* webpackChunkName: "group-foo" */表示路由分组 |
分在同一个组内的组件,当请求其中某一个组件时,组内其它组件也会同时请求。
关于路由懒加载的详细文档,可参考如下链接:
https://router.vuejs.org/zh/guide/advanced/lazy-loading.html
@babel/plugin-syntax-dynamic-import 插件介绍传送门
npm
1 | npm install --save-dev @babel/plugin-syntax-dynamic-import |
打开 vue-ui
面板,选择开发依赖,输入 @babel/plugin-syntax-dynamic-import
进行安装。
然后打开 babel.config.js
文件,在 plugins
数组内添加我们安装的依赖: '@babel/plugin-syntax-dynamic-import'
,具体位置见下文所示:
1 | // 项目发布阶段需要用到的 babel 插件 |
最后,将每一个组件更改为懒加载的形式:
项目上线
- 通过 node 创建 web 服务器。
- 开启 gzip 配置。
- 配置 https 服务。
- 使用 pm2 管理应用。
通过 node 创建 web 服务器
创建 node
项目,并安装 express
,通过 express
快速创建 web
服务器,将 vue
打包生成的 dist
文件夹,托管为静态资源即可,关键代码如下:
1 | const express = require('express') |
第一步,先创建一个文件夹,这里命名为 vue_shop_server
,然后通过 Code
打开。
新建一个终端,输入 npm init -y
执行,初始化包管理配置文件。
初始化完成后,执行 npm install express -S
安装 express
接下来,将我们 vue
项目通过 build
打包得到的 dist
文件夹复制一份,粘贴到我们的 vue_shop_server
文件夹内,然后再新建一个 app.js
入口文件,结构图如下图所示。
测试服务器是否能够运行,新建终端,执行 node .\app.js
命令。如果发现输出了 web server running at http://127.0.0.1
则表示服务已经启动了。
开启 gzip 配置
配置完之前服务之后,我们打开网站后,发现请求网络中文件体积依旧是很大,如下图所示。
使用 gzip
可以减小文件体积,使传输速度更快。
可以通过服务器端使用 Express
做 gzip
压缩。其配置如下:
1 | // 安装相应包 |
此时的 app.js
文件代码如下所示,注意,一定要把启用中间件放在托管静态资源之前! 不然 gzip
压缩不会生效。
1 | const express = require('express') |
配置 HTTPS 服务
为什么要启用 HTTPS 服务?
- 传统的
HTTP
协议传输的数据都是明文,不安全 - 采用
HTTPS
协议对传输的数据进行了加密处理,可以防止数据被中间人窃取,使用更安全
申请 SSL 证书(https://freessl.org)
- 进入 https://freessl.cn/ 官网,输入要申请的域名并选择品牌。
- 输入自己的邮箱并选择相关选项。
- 验证 DNS(在域名管理后台添加 TXT 记录)。
- 验证通过之后,下载 SSL 证书(
full_chain.pem
公钥;private.key
私钥)。
在后台项目中导入证书
1 | const https = require('https'); |
此时 app.js
配置代码如下:
1 | const express = require('express') |
使用 pm2 管理应用
① 在服务器中安装 pm2
:npm i pm2 -g
② 启动项目:pm2 start
脚本 --name
自定义名称
③ 查看运行项目:pm2 ls
④ 重启项目:pm2 restart
自定义名称
⑤ 停止项目:pm2 stop
自定义名称
⑥ 删除项目:pm2 delete
自定义名称
解决Error: ENOENT: no such file or directory, scandir ‘xxx\node-sass\vendor’
解决方案是执行以下方法:
1 | npm rebuild node-sass |