1

Hello World

所有的入门教程几乎都从“Hello World”讲起,这个也不例外。

项目初始化

接上文,我们的项目目前还是个空壳子,什么都没有,现在要先进行项目初始化操作。

  1. 打开vs code里的Terminal,通过点击View-Integrated Terminal来打开内置的Terminal
    图片描述
  2. 执行npm init命令来创建package.json文件,许可证那我该成了MIT,其它基本都是默认,直接回车即可
    图片描述
    执行完上述命令后,根目录下会新增一个package.json文件,其文件内容,上图已经展示了。
  3. 安装koa及对应的types,这里建议再安装一遍typescript,这样可以保持其版本跟着这个项目走,而不是全局

    npm install koa --save
    npm install @types/koa --save-dev
    npm install typescript --save-dev

    执行完上述命令后根目录下会新增package-lock.json文件,这个文件是只有npm v5.0以上版本才会生成的,其与yarn工具生成yarn.lock文件类似,主要是用来记录已安装模块的整个依赖关系,下次install时直接根据该文件去获取依赖库,具体情况可以看官方文档:https://docs.npmjs.com/files/...
    --save选项指将其该依赖保存至package.json中的dependencies下,如果后面有-dev,则保存至devDependencies

配置tsconfig

安装好一些基础依赖库之后,我们需要配置一下tsconfig,这个配置文件用于typescript将/.tsx?/文件编译成js,里面有很多配置项,具体可以查看这个中文文档:https://tslang.cn/docs/handbo...
根目录下面新建一个tsconfig.json文件

// ./tsconfig.json

{
  "compilerOptions": {
    "outDir": "./dist/",
    "target": "es5"
  }
}

最简单的配置就是上面这样,设定好要编译后的js版本(target),和编译后js要输出到的所在目录(outDir)。

PS:为啥要用typescript,因为ts是es的超集,还有类型检查,另外不再需要babel,简单来说,babel有的ts都有,babel没有的ts也有

创建服务端入口代码

我们在服务端目录下新建index.ts作为服务端入口,另外新建一个config.ts作为服务端配置项文件。

// ./src/server/config.ts

export default {
  port: 3344,
};
// ./src/server/index.ts

import * as Koa from 'koa';

import serverConfig from './config';

const app = new Koa();

const { port } = serverConfig;

app.use((ctx: Koa.Context, next) => {
  ctx.body = 'hello world';
  next();
});

app.listen(port, () => {
  console.log(`Koa app started at port ${port}`);
});

疑问一:为何要import * as Koa from 'koa';而不是import Koa from 'koa';?

答:这个问题涉及到import语句的基本语法(见MDN import),很多同学在配合babel的时候都习惯于使用后者这种方式。前者导入所有内容,后者导入默认值。查看koa的源码可见其使用module.exports来设置要导出的内容,根据上述tsconfig中target为es5,此时ts会使用对于es5的默认模块规范即commonjs来处理这些导入导出的模块,而koa源码中并没有设置导出的默认值,即default值,所以需要使用前者这种写法,而babel会做额外的处理(见exporting 'exports.default' rather than 'exports'),使得可以使用后者这种写法。

疑问二:我就想在ts里使用import Koa from 'koa';这种写法,该怎么办?

答:在tsconfig.json中添加如下属性:

// ./tsconfig.json

{
    ...
    "compilerOptions": {
        ...
        "allowSyntheticDefaultImports": true, // 允许从没有设置默认导出的模块中默认导入。这并不影响代码的显示,仅为了类型检查。
        ...
    }
    ...
}

疑问三:为何不直接import { port } from './config';而要写两行代码?

答:import语句中的{ a },和es6中const { b } = xxx;并不是同一回事,前者是导入模块的单个成员a,后者是解构xxx对象的属性b,而port根本不是config导出的模块成员之一,config只导出了一个模块成员即default。

疑问四:Koa.Context是什么东西?“ctx: Koa.Context”又是什么语法?

答:ts中对于变量可使用:对其进行类型声明,这里的Koa.Context即ctx上下文的类型。
图片描述
我们将鼠标移上去可以看到简要信息,点击可以跳转到详细的类型声明文件中看到具体的定义。

编译ts文件

我们使用tsc命令来编译ts文件,为了方便调用,我将编译命令写入了package.json文件中的scripts属性下。

// ./package.json

{
    ...
    "scripts": {
        ...
        "tsc": "tsc -w -p tsconfig.json",
        ...
    },
    ...
}

执行以下命令:

npm run tsc

图片描述

可以看到控制台出现上述信息,且不能再进行输入命令了,另外我们在根目录下发现多出一个dist目录,里面有两个文件,config.js和index.js。

疑问五:为什么生成的文件不是在./dist/server目录下,而是直接在./dist下了?

答:这个可以说(我猜测,可能有配置方法,但目前我没找到)是一个bug,主要表现就是被编译的ts文件都处于一个目录下,那么生成的js文件都会直接被导出到dist目录下,为了避免此问题,我们在./src/client目录下新建一个空的index.ts文件,重写执行编译命令即可生成正确目录下的文件了。

启动服务器

我们使用node来启动我们的koa app,同样我将该命令放在了package.json文件中。

// ./package.json

{
    ...
    "scripts": {
        ...
        "dev": "node ./dist/server/index.js",
        ...
    },
    ...
}

执行以下命令:

npm run dev

打开浏览器,访问以下地址:

http://localhost:3344

可见hello world出现。

疑问六:怎么再开一个vs code里的terminal?

答:如下图,在原terminal窗口右上角按小加号即可
图片描述

Thanks

By devlee


devlee
1.3k 声望31 粉丝