我曾在本系列第二篇“H5必知必会之像素级还原设计稿”的最后写道:

……读者可能会不由自主地猜测这个系列第三篇的主题是什么?……还有可能会写一写基于某个脚手架快速从头搭建一个H5项目以及实现前端工程化……。

那么,今天我们这一篇的主题就是“快速搭建开发环境”。快速,有多快?答案:取决于你的网速。因为我们真的有这么一个脚手架:qvk。

什么是qvk

qvk是一个集成现代前端工程化最佳实践的通用Web开发环境,可用于开发传统C/S架构的Web应用、SPA(单页应用)、H5(App内嵌页)等。

qvk脱胎于多个360前端项目,集成了开源社区中涌现的优秀框架、工具和最佳实践。qvk初始版集成以下Web框架和打包工具。

  • ThinkJS:基于MVC模式的简单易用、功能强大的Node.js开发框架。
  • Vue.js:渐进式JavaScript框架,前端组件式开发主流选择。
  • Webpack:目前使用最广泛的前端资源模块打包工具。

什么,这里有些新面孔?没关系,不久你就会发现它们都很友好、简单。

搭建开发环境

qvk的Github仓库地址是:https://github.com/qqvk/qvk

打开这个页面,点击“Clone or download”按钮:

点击“复制到剪贴板”图标。打开常用的终端,进入或新建某个项目目录,比如myProject,克隆qvk的代码:

注意,我们给新项目起了一个名字,叫h5project。进入这个目录:

LICENSE和README.md,当然一个是协议,一个是项目介绍。而client、server两个目录,则分别用于保存前端和服务端代码(及依赖)。

为方便开发,我们建议使用VSCode,并通过把code命令添加到路径,从命令行启动VSCode(参见这个链接:https://code.visualstudio.com/docs/setup/mac):

这样,在项目路径下运行code .就可以启动VSCode:

VSCode启动后,按快捷键Ctrl+`切换到终端,再按Cmd+拆分终端(或者鼠标点击图标进行拆分),结果如下:

接下来,分别安装前端和服务端的依赖。左、右终端窗口分别进入server和client目录,并运行npm install安装依赖:

根据每个人的网络状况不同,安装依赖大约耗时10~30秒不等。事实上,这是我们搭建环境中最慢的一步。至于如何加速这个过程,大家可以自行上网搜索相关文章。

安装完依赖,还需要构建一下前端代码,以便生成服务端所需的模板文件和静态资源。简单,只要在client目录下运行npm run build即可:

这一步执行完之后,会在server目录(没错,是在server目录,本文后面会解释)下生成两个目录。

  • view:保存构建生成的模板,供服务端使用
  • www:保存构建生成的模板引用的静态资源(js/css等)

好了,现在我们的开发环境已经具备启动条件了!稍等,在启动之前,还需要说明一下。

如前所述,qvk默认将开发环境分成了前端(client)和服务端(server),两端分别启动Web服务器,端口默认为:

  • 前端:9090
  • 服务端:8900

启动服务后,前端会把所有浏览器请求代理到服务端,即浏览器会自动打开:http://localhost:9090,而所有请求实际上由服务端8900端口响应。之所以这样配置,是为了实现前、后端开发的实时编译和刷新(为什么选这两个端口?没有原因,就是随便选的而已)。

说明结束。接下来就启动服务吧——由于前端服务要代理到后端服务,所以启动顺序是……?没错:先启动后端,后启动前端。

怎么启动?npm start

先启动服务端:

再启动前端:

启动前端,会触发Webpack的初始构建过程,构建完成后,会自动在浏览器中打开http://localhost:9090/

恭喜,看到这个网页,就说明你的开发环境搭建完成了!你说快不快?

上手开发

光搭建好环境还不成,关键是要知道怎么使用这个环境开发自己的项目。

ThinkJS是一个优秀的Node.js MVC开发框架,上手非常容易。这里,server目录其实就是ThinkJS的工作目录。如果忽略保存依赖的node_modules和用于保存运行时配置的runtime,开发中实际用到的只有src、view和www目录,如下图所示:

(考虑到view和www是前端构建生成的,所以这里真正用到的就只有src目录了,哈哈哈。是不是又简单了?)

用ThinkJS开发一个页面,只要简单两步:

  • 根据确定的路由编写控制器方法
  • 在控制器方法中指定渲染页面的模板

我们就以现有的代码为例。src/controller里保存所有控制器代码,其中index.js是默认控制器,而index.js中的indexAction是默认的响应处理函数(如果方法不带Action,则不能响应外部请求,可作为内部方法)。

src/controller/index.js

const Base = require("./base.js");

module.exports = class extends Base {
  async indexAction() {
    return this.display()
  }
  pixelAction() {
    return this.display('pixel_demo')
  }
};

所谓默认,意思就是http://localhost:9090/这个请求,默认会由index.js的indexAction方法来处理。怎么处理的呢?这里倒是极其简单,只有一行代码:

return this.display()

this.display()方法会返回使用默认模板引擎渲染默认模板之后的HTML,作为服务器的响应返回给浏览器。默认模板引擎是Nunjucks(https://mozilla.github.io/nunjucks/),而默认的模板文件就是view/index_index.html:

view/index_index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width,initial-scale=1.0">
  <title>qvk: A Web integrated development environment.</title>
<link href="/static/css/index_index_79ed.css" rel="stylesheet"></head>
<body>
<div class="welcome">
  <div reminder>
    <h2>欢迎使用qvk创建开发环境</h2>
    <p><a href="/index/pixel">H5必知必会之像素级还级设计稿DEMO</a></p>
  </div>
</div>
<script type="text/javascript" src="/static/js/commons_6a84.js"></script><script type="text/javascript" src="/static/js/index_index_79ed.js"></script></body>
</html>

当然,这个HTML模板中可以使用模板引擎支持的各种语法,嵌入变量和语句,以及其他服务端逻辑(这里没有,哈哈,具体可以参考模板引擎的文档:https://mozilla.github.io/nunjucks/)。

服务端开发说完了,接下来看前端。前端代码在client目录中,同样开发中真正用到的只有src目录:

如图所示,src目录下面有一个Webpack的入口文件:index_index.js,而在模板目录_templates_ssr中,有一个同名但不同扩展名的index_index.njk文件(njk就是Nunjucks的简写)。

Webpack会根据这个命名规则,以index_index.njk为模板生成ThinkJS渲染所需的server/view/index_index.html模板,同时会将入口文件中指定的依赖打包后注入到该模板中。

我们看一下入口文件index_index.js:

client/src/index_index.js

import './_static/css/index_index.scss'

哇,只有一行,使用import模块语法引入了一个SCSS文件。这个文件在通过相应的转换生成普通CSS后,会被注入index_index.html模板中:

<link href="/static/css/index_index_79ed.css" rel="stylesheet">

如果这个页面有交互逻辑呢?那就要在入口文件中引入相应的JavaScript文件(可以放在./_static/js/目录下)。同样,Webpack会在构建时把JavaScript打包注入到模板中。

事实上,在开发中,Webpack会自动监控所有入口文件中引入的资源,只要这些资源有修改和保存,就会触发重新构建并刷新浏览器,让我们实时看到修改的结果。

写在最后

本文到此就结束了,真的结束了。此时,难免有读者会问,我们搭建的是H5开发环境吗?是的。你可以点击这个页面中的链接看一看:

你会发现,我们card组件中的所有CSS像素单位都被转换成了视口宽度单位:

如果读者不明白“把像素单位转换成视口宽度单位”是什么意思,请参考本系列第二篇文章“H5必知必会之像素级还原设计稿”,当然还有这个项目源代码。

关于qvk

最后,qvk还很弱小(事实上,它就诞生于本文撰写前几分钟),算不上有新颖创意,它只是一个集成了众多前端优秀开源项目及最佳实践的脚手架。当然,我们还会继续努力为它增加更多有用的配置和更丰富选项,如果你也有类似的想法,欢迎加入qvk贡献者的行列。

大家有什么想法,欢迎留言吧。

标签: webpack

添加新评论