第 01 课:模板功能设计

1 项目模板

我们的项目框架都是基于项目模板生成的。学过 JS 的知道:

function Person(name = 'ant') {
    this.name = name;
}
let man = new Person();

这里 Personman 的原型对象。同样项目模板相当于对象 Person,具体的项目相当于 man。通过项目模板,我们可以事先将项目所需要的功能点定义好,使用的时候只需要像实例化一个对象一样,简单地 new 一下就搞定了。大大地减少重复劳动,屏蔽项目配置的复杂度。

在动手搭建之前,有必要对我们的项目模板进行一个整体规划。我们后面的课程就是按照规划逐个实现。

2 支持哪些功能

2.1 代码检查

JavaScript 是一个动态的弱类型语言,在开发中比较容易出错。同时由于每个人的编码习惯和风格不尽相同,写出的代码风格迥异,时间久了很难维护。因为没有编译程序, JavaScript 代码错误通常需要在执行过程中不断调试,效率很低。

但是,我们不可能人肉进行代码检查,因为当代码量很大的时候,需要耗费很大的精力。所以代码检查我们借助 ESLint 来实现。ESLint 可以让程序员在编码的过程中就发现问题,避免将问题带到执行时。

为什么使用 ESLint?

  • ESLint 的所有规则都是可拔插的。ESLint 不限制开发人员的编码风格。因为其设计的初衷就是为了让开发人员创建符合自己编码风格的规则。当然 ESLint 有一套内置的默认规则。但是可以修改甚至自定义自己的规则一切都是可拔插的。
  • 每条规则可以自由地开关。开发人员可以根据自己项目的需要决定是否开启某条规则。也可以修改检查结果的告警等级,决定抛错还是只是警告。

一个简单的示例:

let foo = bar;
1:5 - 'foo' is assigned a value but never used. (no-unused-vars)

如果我们在 ESLint 配置文件中启用了 no-unused-vars 规则。那么当代码中出现定义未使用的变量时,就会给出错误提示。

至于 CSS 的检查,这里我们使用 stylelint 来处理。stylelint 功能非常强大,可以支持 scss、sass、less 以及 sugarss 的语法检查。此外,stylelint 和 ESlint 类似,也是提供了插件机制,开发者可以自己来定义规则,根据自己的团队定制一套统一的规范,避免样式错误。

我们看一个简单的示例。

有下面这样一段 css 代码:

/* */
a { color: #FFF; }

stylelint 规则如下:

"rules": {
    "comment-no-empty": true,
    "color-hex-case": "lower"
  }

stylelint 提示注释内容不能为空,字体颜色的 16 进制表示字母不允许大写。

1:1 error Unexpected empty comment (comment-no-empty)
3:12 error Expected "#FFF" to be "#fff" (color-hex-case)

2.2 本地开发环境

在日常开发中,前端开发经常做的是完成部分功能和页面的开发后,去刷新一下浏览器,看一下效果是否符合预期。所以能有一个本地 Web 服务器加载我们的页面,并且当代码变动的时候自动刷新页面,可以减少开发同学的切换成本,提升开发效率。

我们在模板中使用 webpack-dev-server 作为 一个简单的 Web 服务器,由于 webpack-dev-server 内置了模块热替换(Hot Module Replacement 或 HMR),页面被修改后自动重新加载。

// package.json
"scripts": {
    "dev": "webpack-dev-server --open"
}

在 Webpack 配置文件中完成 dev-server 的配置后,我们只需要在 package.json 文件中添加一个 script 命令。在进行开发时,只需要一个简单的 npm run dev 命令就可以启动本地服务器。

2.3 mock server

前后端分离后,双方有清晰的边界,后端负责业务逻辑的编写,前端负责视图逻辑的开发,双方的数据传输通过 API 实现。前后端共同约定一份接口文档,接口文档中规定了接口名称、入参、出参以及数据结构等。

但仅仅有一份静态的接口文档还远远不够,我们需要的是在开发的阶段就能像在线上一样去调用服务端接口获取数据。

所以,Mock 是前后端分离模式下一项必备的功能。

我们采取的做法是在项目模板中实现一个 mock server,来响应本地请求。同时假数据通过 mockjs 来生成。

由于我们的本地开发环境与 mock server 运行在不同的端口上,因此我们还需要在 Webpack 中提供的 proxy 功能将我们的请求转发到 mock server 上去。

graph LR
A(dev server)-->B(proxy server)
B(proxy server)-->C(mock server)

2.4 构建

现在的前端开发基本上都是采用了模块化的开发方式,而且在代码中使用了大量的 es6+ 语言特性。但宿主浏览器中对新特性的支持不一。我们的代码无法直接运行在浏览器中,所以需要对代码进行构建打包,将代码编译成浏览器都可运行的代码。

// webpack.config.js
...
output: {
      path: path.join(__dirname, './build'),
      publicPath: opt.publicPath,
      // 给线上环境的资源添加hash
      filename: 'js/[name]' + hash(needHash, 'chunk') + '.js',
      chunkFilename: 'js/[name]' + hash(needHash, 'chunk') + '.js',
}
...
plugins: [
    ...
      new webpack.optimize.UglifyJsPlugin({
        compress: {
        // 删除console和警告
            drop_console: true,
            warnings: false
        }
      })
      ...
]

由于目标代码的应用场景不同,我们需要针对不同的环境来进行构建。比如,针对测试环境运行的代码,由于需要不断进行调试,我们一般不清除代码中的注释和 console。由于代码部署无需考虑备份,不给构建出的文件添加 hash。线上环境构建的时候,我们需要尽可能减小文件的体积,同时需要考虑部署后不覆盖线上资源,所以需要在构建时剔除代码中的注释和调试语句,对代码进行混淆压缩,给文件添加 hash。

现在绝大多数现代浏览器都已经支持了原生的 ES2015,编译后的包通常都比原生的 ES2015+ 代码会更冗长,运行更慢。所以因为要支持更老的浏览器而为它们交付笨重的代码是一种浪费。我们在模板中可以针对现代浏览器打出体积更小的包。

  • 现代版的包在被支持的浏览器中通过 <script type="module"> 进行加载,使用 <link rel="modulepreload"> 进行预加载。
  • 旧版本的包会通过 <script nomodule> 加载,支持 ES modules 的浏览器会忽略该引用。

2.4 部署

构建完成后,最后一步就是把前端资源发布到服务器了。假定我们的前端项目都是完全的前后端分离的,这意味着前端的资源需要和服务端分开部署。

比如,我们为专门准备一个 OSS 服务器用来部署入口文件,准备另一个 OSS 服务器部署 js、css 和图片等资源。

// package.json
"scripts": {
    // 假定我们的部署逻辑在deploy.js中
    "deploy": "node deploy.js"
}

部署我们会用到两个 npm 包,一个是 vinyl-ftp,专门用以登录我们的 OSS 服务器,另一个包是 vinyl-fs,用来将本地的资源发布到远程服务器。最后我们在 package.json 文件中配置 deploy 命令。部署操作只需要执行 npm run deploy 即可。

2.5 Qdebug

相信大家在测试过程中,有一个问题经常会遇到。总是有测试同学把一些本属于服务端的 bug 提给前端。前端同学看到 bug 后,按照复现步骤排查一遍,“咦!这个问题是接口中数据有问题导致的!”赶紧转给服务端同学,并且心中有一丝不爽。

所以,很有必要开发一个小工具辅助测试同学,为他们分析 bug 产生的原因,准确指派 bug 提供事实依据。

因此,我们在项目模板中要实现一个 Qdebug 小工具。

<script>
  // 初始化
  var debug = new QDebug();
</script>

Qdebug 基于 vconsole 进行扩展,可以将接口请求中的详细接口数据打印出来,同时会生成一个当前前端代码的版本号。测试同学通过版本号就可以知道前端的资源是不是已经更新,通过查看详细的接口数据就可以准确判断 bug 的归属。

2.6 自动化测试

自动化测试在 Web 工程中扮演重要的角色。自动化测试还可以与持续集成进行结合,通过机器来保证工程的质量,提升团队整体的效能。因此在前端工程化的建设过程中,自动化测试也是很重要的一环。

自动化测试根据粒度的不同,基本可以分为:单元测试、接口测试、端到端测试(也叫功能测试)。在前端工程中得到应用的主要是接口测试和端到端测试。

单元测试,是站在开发人员的视角,把代码划分成一个个的代码单元逐个进行测试,看返回的结果是否符合预期。

我们通过 Karma+Mocha+Chai 来实现单元测试功能。执行单元测试很简单也是通过 npm script 来调用,例如:

npm run test:uinit

端到端测试是站在用户的视角,把 Web 应用当成一个黑盒,模拟用户的真实使用场景,比如在页面中输入文字,点击搜索。看测试结果是不是符合预期。端到端测试框架有不少,比如 Nightwatch、TestCafe、CasperJS。在本模板中,我们选用 Nightwatch 来实现端到端测试,主要是因为使用 Nigthwatch 编写的代码非常简洁。

执行端到端测试很简单通过 npm script 来调用,例如:

npm run test:e2e

3 目录结构

说完了模板要实现的主要功能后,我们来看一下项目模板的整体目录结构:

boilerplate-vue
├── package.json
├── README.md
├── .gitignore
├── .babelrc
├── config
├── build
├── mock
├── test
|   ├── unit
|   └── e2e
├── src
|   ├── assets
│   ├── components
│   ├── router
│   ├── pages
│   ├── app.js
│   └── App.vue
└── public
    ├── index.html
    └── favicon.ico

主要的一些目录和文件功能如下:

  • src 中存放业务代码。其中 src/app.js 是项目构建的入口文件,src/App.vue是视图层的入口文件,src/pages 中放置不同的页面,src/components 中放置 Vue 组件,src/router 中放置 router 相关的文件,src/assets 中放置静态资源如图片、字体等。
  • mock 存放 Mock 的假数据。
  • test 用于放置测试相关的文件。
  • build 用于放置构建相关的文件。
  • config 用于放置配置相关的文件。
  • public 用于放置公用的静态资源,如 HTML 入口模板文件、站点的小图标。
  • package.json npm 模块的配置文件。
  • .babelrc babel 的配置文件。
  • .gitignore 用于指定哪些文件不提交到 Git 仓库。
  • README.md 项目的介绍和使用文档。

点击了解《透视前端工程化》

总结

本节我们对模板的功能进行了系统的规划和目录结构设计。模板功能覆盖了开发阶段、测试阶段、构建阶段、部署阶段。

文中对各个功能的实现所需要用到的技术和工具也进行了简单的介绍,大家对每个部分有个大概的印象即可。在后面的章节中,我们会有更为详尽的讲解。

注意!!! 为了方便学习和技术交流,特意创建了《透视前端工程化》的读者群,入群方式放在第 03 课文末,欢迎已购本课程的同学入群交流。

评论将由博主筛选后显示,对所有人可见 | 还能输入1000个字符 “速评一下”
©️2020 CSDN 皮肤主题: 1024 设计师:上身试试 返回首页
实付 49.90元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值