vscode调试
断点
无须多言
模式
两种模式
- 一种是通过node的launch,也就是直接启动项目的入口。这种方式最为直接,但是实际上并不是很方便,因为每一次调试都需要重新启动项目。
- 另一种是通过attach的方式,使用node-inspector进行调试。
1 | { |
Yoki
无须多言
两种模式
1 | { |
pt和px的关系就是—— 1pt(独立像素) 里面有几个像素(物理像素)点 (比如 1pt里面有1个px,也可以有2个,3个,分别对应上图的@1x,@2x,@3x)
禁止缩放
1 | <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" /> |
引用淘宝的flexible.js方案
使用postcss-pxtorem在构建过程中将px转为rem
1 | postcss: [require('postcss-pxtorem')({ |
在rem方案中,如果没有特殊处理,1px的线条在 dpr 大于 1 的设备会比较粗。根本原因是1px可能会占用两个物理像素点或以上。
可以采用 transform: scale(0.5);来解决,在上面的selectorBlackList添加’.ui-hairline’
首先看一下传统的web开发,传统的web开发是,客户端向服务端发送请求,服务端查询数据库,拼接HTML字符串(模板),通过一系列的数据处理之后,把整理好的HTML返回给客户端,浏览器相当于打开了一个页面。这种比如我们经常听说过的jsp,PHP,aspx也就是传统的MVC的开发。
SPA应用,到了Vue、React,单页面应用优秀的用户体验,逐渐成为了主流,页面整体式javaScript渲染出来的,称之为客户端渲染CSR。SPA渲染过程。由客户端访问URL发送请求到服务端,返回HTML结构(但是SPA的返回的HTML结构是非常的小的,只有一个基本的结构)。客户端接收到返回结果之后,在客户端开始渲染HTML,渲染时执行对应javaScript,最后渲染template,渲染完成之后,再次向服务端发送数据请求,注意这里时数据请求,服务端返回json格式数据。客户端接收数据,然后完成最终渲染。
SPA虽然给服务器减轻了压力,但是也是有缺点的:
为了解决如上两个问题,出现了SSR解决方案,后端渲染出首屏的DOM结构返回,前端拿到内容带上首屏,后续的页面操作,再用单页面路由和渲染,称之为服务端渲染(SSR)。
SSR渲染流程是这样的,客户端发送URL请求到服务端,服务端读取对应的url的模板信息,在服务端做出html和数据的渲染,渲染完成之后返回html结构,客户端这时拿到的之后首屏页面的html结构。所以用户在浏览首屏的时候速度会很快,因为客户端不需要再次发送ajax请求。并不是做了SSR我们的页面就不属于SPA应用了,它仍然是一个独立的spa应用。
SSR是处于CSR与SPA应用之间的一个折中的方案,在渲染首屏的时候在服务端做出了渲染,注意仅仅是首屏,其他页面还是需要在客户端渲染的,在服务端接收到请求之后并且渲染出首屏页面,会携带着剩余的路由信息预留给客户端去渲染其他路由的页面。
从服务端到客户端的一个过程,主要查看官网。
注意:vue的生命周期created和beforeCreated在客户端和服务端同时执行。
1 |
|
假设域名为a.com,该域名映射到pc端网站(vue的spa)。a.com/m映射到服务端(nuxt启动的服务,移动端网站)
1 | upstream gateway_svr { |
/m
pm2可使进程常驻
1 | module.exports = { |
最好配置脚本在package.json里
我们希望直接通过服务器重启之后能自动启动
我们可以通过shell远程执行一些命令,来达到我们部署系统的目的。这样我们就可以不用sftp可视化界面来拖动,省去了这一步。
一般我们是通过ssh来登录服务器
1 | ssh user@remoteNode "cd /home ; ls" |
远程执行的内容在“<< eeooff ” 至“ eeooff ”之间,在远程机器上的操作就位于其中
1 | ssh user@remoteNode > /dev/null 2>&1 << eeooff |
需要注意以下
先使用tar 命令压缩文件,减少文件上传的大小,过去了服务器再解压
1 | # 移除本地压缩文件 |
有了之前的基础,我们现在可以讲讲一个成熟的脚手架是怎么做了。vue-cli作为vue的脚手架,给如此多的前端开发者使用,已经算是成熟了吧。
这里我们参考vue-cli的源码,基于rollup和typescript一步步搭建。
以下我们的命令仍然是ds~,模板是ds-cli-lib-template
1 | ├─ bin # 打包文件目录 |
现如今,webpack用来开发应用(热更新hmr,代码拆分等),rollup用来开发类库(简单易上手,打包后代码能读懂,至于其他的特性webpack基本已支持)。
现在来明确我们的需求
1 | //rollup.config.js |
npm脚本命令(“scripts”字段)1
2
3
4{
"clean": "rm -rf ./bin && mkdir bin",
"build": "npm run clean && rollup --config"
}
是一些非常基础的东西,我们一般不放很复杂的逻辑在入口文件里。
1 | const cmd = require('commander'); |
我们打包到bin文件夹下后,配置一下package.json的bin字段为bin/ds.js,然后发布npm试一下命令。如果失败,请重新审视上述流程。
ds init
1 | if(当前目录下构建){ |
大家也看到了,其实最重要的就是generate函数~
generate函数里面用到了metalsmith,这个就相当于我们之前用的gulp,通过不断地编写中间件来优化打包后的结果。
1 | function generate(){ |
我们在模板(如ds-cli-lib-template)目录下需要构造meta.js,自定义我们所需的字段
1 | module.exports={ |
到高级阶段之后,其实已经不分前后端了。因为前后端领域的互通之处会越来越多。
技能是看得到的部分,当你和一些资深开发人员接触时,往往能直观感受到的是技能。但是他们真正资深的原因,在于眼界、思维和心态(看不到的部分)。
中年危机
这里先简单了解一下基础知识,接下来会基于typescript和rollup参考写一个较为完整的脚手架(动态模板),以下只能拉取静态模板。
这里假设我们的脚手架名字是ds-cli,以下都用这个名字。我们在命令行使用脚手架命令为ds
当我们bin字段指向我们的目标文件main.js,同时目标文件开头具有
1 | //这里是main.js |
这样当我们发布上npm,别人下载下来后,就可以直接使用ds命令了。
1 | const cmd = require("commander"); |
我们通过询问用户来获得一定的交互,这样可以知道用户需要什么
1 | //比如我们在上面那个action里面搞事情,即ds init之后问用户 |
1 | const download = require("download-git-repo"); |
可以使用handbars,模板语法简单
1 | //这个是通过download-git-repo拉下来的package.json |
然后我们通过读取文件字符串给handbars编译一下拿到的变量,再写入
1 | //通过询问拿到的answers |
终端加载效果:ora,有个loading效果
1 | const spinner = ora("正在下载模板..."); |
打印日志的特殊标志:log-symbols
1 | #!/usr/bin/env node |
产品迭代周期的开始——产品经理提出了一堆新功能(可以说一个功能【jira】对应一个 feature 分支),新建 feature 分支到完成发布的生命周期如下
1.git flow feature start 180827-radar109(新建分支 feature/180827-radar109 并切换)
2.git flow feature publish 180827-radar109 (将该版本推到远程仓库,便于小伙伴获取)
3.git flow feature finish 180827-radar109(完成该功能分支,并删除。同时切回 develop 分支)
4.发布测试平台交由提测,假设测试通过,直接跳到 7。测试不通过有 bug,跳到 5。
5.git flow bugfix start 180827-radar109(新建分支 bugfix/180827-radar109 并切换,也许测试提出了新的 jira 来修改,这里不一定是 109)
6.与 2-3 步骤类似
7.每天中午自己的分支拉一遍 develop 分支(防止自己的 feature/bugfix 分支不是最新)
8.产品经理提出的所有新功能,小伙伴全部完成之后。跟产品经理确认这个周期不再有新的功能,同时他在灰度测试平台确认可以发布线上,该周期基本结束。
9.git flow release start 产品版本(从 develop 分支新建 release/产品版本)
10.git flow release publish 产品版本(发布到远程仓库,便于大家进行小修小改,无需进行 bugfix 分支,这是因为之前 4 步骤针对每个 feature 已经提测,这里理论上只是小修改如文案不到位之类)
11.release 版本发布正式平台,一天时间缓冲进行 UAT 测试,若无问题第二天进行第 11 步骤,若有问题直接针对该 release 分支修改
12.git flow release finish 产品版本(完成 release 分支,并合并到 develop 和 master 分支,同时使用该版本名字打 tag)
13.在 wiki 某角落,写下该周期之发布记录。同时使用 release 脚本运行记录。
14.发布平台使用 master 分支,发布所有线上机器。
产品经理或者客户提出线上有 bug,需要立刻修改的作法如下
需要注意,hotfix 大多是紧急情况,测试人员有可能不到位,这里更多依赖自测,然后直接发布 master
1.git flow hotfix start 版本名字-专有名字(可能有多个 hotfix 给多个小伙伴修改,这里会从 master 切出分支 hotfix/版本名字-专有名字)
2.git flow hotfix publish 版本名字-专有名字(push 到远程仓库,万一小伙伴突然有事或者电脑挂了,其他小伙伴可以接力改)
3.git flow hotfix finish 版本名字-专有名字(合并到 master 分支,并对 hotfix 版本打 tag,然后删除)
4.发布平台使用 master 分支,发布所有线上机器。
项目经理和客户确认可能只有两个里程碑节点,这时候迭代周期如何确定
1.内部和项目经理制定更为详细的周期节点,或使用石墨管理,或使用 wiki 管理(工具只是手段)每个周期内更细致的需求,多个周期节点的制定有利于发布线上,给项目整体以信心
2.如果两个里程碑节点发布线上(线上只会存活两次正式版本),大家认为已经足够,则无须讨论
3.具体情况具体分析,重要的是人而不是死板的步骤
产品在迭代周期中间变更部分需求
1.视需求变更的复杂度而定,如果影响到周期结束时间,可以和产品经理商量修改结束时间,如果时间不能更改,则寻求更多的资源(研发,加班)
2.频繁变更需求则应拒绝,请产品思考清楚
git branch 功能很强大,但是没有一套模型告诉我们应该怎样在开发的时候善用这些分支。而 Git Flow 模型就是要告诉我们怎么更好地使用 Git 分支。Git Flow 模型也有相关的插件,可放心食用。
可以明确的是,产品开发迭代必须是有一个周期的。这个周期时间,可以由 pm(项目或者产品)指定,不论多短或多长,都应视为一个周期。此概念可帮助该 git-flow 模型执行。
Master 以及 Develop 这两个分支是长期分支,他们会一直存活在整个 Git Flow 里,而其它的分支大多会因任务结束(执行 finish 命令)而被自动删除,这样无需担心有冗余分支。
Release 是需要打版本号的分支。例如 1.1.2(待定)。
除上述三种分支,其他分支命名规范统一以:功能分支-年/月/日:feature/180827。
倘若有 jira 链接,假设是 radar(该项目)109,可以附上:feature/180827-radar109
团队如果采用 Angular 的提交规范,有方便的插件,可放心食用。
无法定义自己的模块/组件(scopes),比如项目具体业务的页面
adapter
配置 commit message,例如,要使用 Angular 的 commit message 格式,可以安装 cz-conventional-changelog
,执行commitizen init cz-conventional-changelog --save --save-exact
git commit
以后提交使用git cz
自定义程度较高,可以有自己想要的模块
.cz-config.js
文件,如下1 | "use strict"; |
1 | { |
git commit
以后提交使用git cz
鉴于 vscode 有很方便的提交 git 的图形化按钮,有些童鞋可能会一不小心就提交了自己的信息
@commitlint/config-conventional
和@commitlint/cli
(检查).commitlintrc.js
,如下1 | "use strict"; |
commitlint-config-cz
(自定义) 和@commitlint/cli
(检查)commitlint.config.js
,如下1 | const disabled = 0 |
1 | "husky": { |
standard-version
(很多特性)这样的工具, 自动生成 CHANGELOG1 | "script": { |