nextJS项目内引入TS的基础设施+使用ts书写express服务端(express+客户端)

Next本来就内置了ts的webpack配置、babel配置,想要引入的成本很低。
但是难点在于:我们的nextjs项目另外采用了express作为服务端服务器框架,如何将express内的Node代码也改造成使用ts呢?
还有最痛苦的问题就是不知道express怎么写ts啊啊啊,我原本的文件都是用CJS导入导出的,但是根本不支持导出type,导致我写个type到处都是报错😭

总之把一些步骤和解决措施放在下面。

react项目引入ts基础配置

参考:https://juejin.cn/post/7128929470618009608
Next typescript 文档

1. 安装新的依赖

1. 安装typescript

npm i -D typescript

安装完typescript后,其实ts内置了一个tsc命令,tsc命令可以生成配置文件、检查ts的类型错误。
使用tsc --init创建一个tsconfig.json文件,里面就是解析ts文件的各种配置。
一份可供参考的tsconfig文件如下:
🔗tsconfig官方文档文档链接

{
  // 编译选项
  "compilerOptions": {
    // 生成代码的语言版本:将我们写的 TS 代码编译成哪个版本的 JS 代码
    "target": "esnext",
    // 生成代码的模块化标准
    "module": "esnext",
    // 指定要包含在编译中的 library
    "lib": ["dom", "dom.iterable", "esnext"],
    // 允许 ts 编译器编译 js 文件
    "allowJs": true,
    // 跳过类型声明文件的类型检查
    "skipLibCheck": true,
    // es 模块 互操作,屏蔽 ESModule 和 CommonJS 之间的差异
    "esModuleInterop": true,
    // 允许通过 import x from 'y' 即使模块没有显式指定 default 导出
    "allowSyntheticDefaultImports": true,
    // 开启严格模式
    "strict": true,
    // 对文件名称强制区分大小写
    "forceConsistentCasingInFileNames": true,
    // 为 switch 语句启用错误报告
    "noFallthroughCasesInSwitch": true,
    // 模块解析(查找)策略
    "moduleResolution": "node",
    // 允许导入扩展名为.json的模块
    "resolveJsonModule": true,
    // 是否将没有 import/export 的文件视为旧(全局而非模块化)脚本文件
    "isolatedModules": true,
    // 编译时不生成任何文件(只进行类型检查)
    "noEmit": true,
    // 指定将 JSX 编译成什么形式
    "jsx": "react-jsx",
    // 如果指定,.ts文件将被输出到此目录中,否则留在源文件的目录结构中
    "outDir": "build/dist",
    // 当前的根目录
    "baseUrl": ".",
    // 不需要定义:所有可见的“node_modules@types/**”包都会被默认收集。但是如果被定义了那就不会默认收集了
    // "types": ["node"],
  },
  // 指定允许 ts 处理的目录
  "include": ["**/*.ts","**/*.tsx","next-env.d.ts"],
  // tsc排除的目录
  "exclude": ["node_modules", "build", "dist"]

}

ts文件中存在的几个定义:

  • .ts 或 .tsx文件
    .ts ts 文件的后缀名 .tsx 是在 TS 中使用 React 组件时,需要使用该后缀
  • d.ts 文件
    .d.ts 类型声明文件,用来指定类型,可以定义全局type。
    不会生成 .js 文件,仅用于提供类型信息,在.d.ts文件中不允许出现可执行的代码,只用于提供类型

2. 引入ts的babel解析 & webpack的ts-loader(next/babel已经帮我们集成了这一步)

npm i -D @babel/preset-typescript ts-loader 

然后在.babelrc中配置preset。
webpack中配置ts-loader,进行编译过程中的类型校验,如果类型错误将中断校验。

babel编译和ts-loader编译的区别与互补说明:🔗https://juejin.cn/post/7127206384797483044

next.config中提供了编译中跳过tsc的方式:

 typescript: {
   ignoreBuildErrors: true, // 跳过build时的ts校验,交给eslint和husky拦截
 },

2. 引入常用的框架中的ts type

引入之后不用操作,tsc会自动找到@/types包下的文件的。

npm i -D @types/lodash @types/react @types/node @types/express

3. 完善ts的eslint配置

ts没有专门的tslint,它的创始人推荐使用eslint插件配置在eslint中。

TSLint is deprecated.
See this issue for more details: Roadmap: TSLint → ESLint. If you’re interested in helping with the TSLint/ESLint migration, please check out our OSS Fellowship program.

npm i -D @typescript-eslint/eslint-plugin @typescript-eslint/parser

同时在husky的命令中增加.ts / .tsx
eslintrc.js中配置:

  overrides: [
    {
      files: ['**/*.ts', '**/*.tsx'],
      extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended'],
      parserOptions: {
        project: './tsconfig.json',
      },
      parser: '@typescript-eslint/parser',
      rules: {
        // 不允许显式声明any
        '@typescript-eslint/no-explicit-any': 2,
      },
    },
  ],

4. 编写tsx文件,.d.ts文件

测试类型校验、eslint校验是否可行。

express服务端引入ts

参考:
next-express-github-demo
使用TS来编写express服务器

我这边的express服务端文件都在/server文件夹下,项目目录结构大概如下:
.
├── build 编译文件
├── server 服务端
├── src 客户端
├── tsconfig.server.json
├── tsconfig.json
├── eslintrc.js
├── next.config.js
├── ……
└── src

配置服务端的类型校验

1. 安装新的依赖(上面已经安装过了)

npm i -D @types/node @types/express

2. 生成node端专用的tsconfig.json文件。

我取名为tsconfig.server.json

 {
  // 引入扩展
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "target": "ES6",  // 指定生成的JS代码的ECMAScript版本
    "module": "CommonJS", // 指定生成的JavaScript模块系统
    "strict": true,   // 开启所有严格类型检查选项
    "esModuleInterop": true,  // 启用esModuleInterop以兼容CommonJS和ES模块
    "skipLibCheck": true,  // 跳过定义文件的类型检查
    "outDir": "build/dist",  // 编译输出目录
    "rootDir": ".",  // 源码目录
    "resolveJsonModule": true,  // 允许导入JSON模块
    "sourceMap": true  // 生成source map文件
    "allowSyntheticDefaultImports":true, // babel转换时可配置:即使CJS模块本身没有default导出,仍然可以使用default导入。(兼容ECM / CJS)
    "moduleResolution":"Node", // 使用Nodejs方案解析
  },
  "include": ["server/**/*.ts"],  // 包含的TypeScript文件
  "exclude": ["node_modules"]  // 排除的目录
}
baseUrl
  • 作用: 决定非相对模块导入时的基准目录。
  • 使用场景: 在代码中使用非相对路径(例如,import { x } from 'myModule')时,TypeScript会根据baseUrl配置的路径作为起点寻找模块。
  • 默认值: 如果未指定,使用当前目录。
  • 示例: 如果设置了baseUrl"./src",然后在代码中使用import { x } from 'utils/helper',TypeScript将会在src/utils/helper.tssrc/utils/helper/index.ts中寻找模块。
rootDir
  • 作用: 用于控制编译器如何安排输出文件的目录结构。
  • 使用场景: 影响编译输出的目录结构,通常与outDir一起使用来规范地管理编译后的代码。
  • 默认值: 如果未指定,则TypeScript自动推断,通常为输入文件的共同上级路径。
  • 示例: 假设项目结构是src/utils/helper.ts,设定rootDir"src",而outDir"dist",那么编译时helper.ts会被输出为dist/utils/helper.js
allowSyntheticDefaultImports

可以影响模块的导入方式。启用这个选项后,即使模块本身没有default导出,仍然可以使用default导入。

  • 在CommonJS中,模块并没有默认的default,但Babel 转译会生成一个名为 default 的导出,使得ES6可以像导入默认导出那样导入CJS对象。

  • 如果项目使用了 Babel 来转译,可能会生成允许默认导入的代码形式,启用该选项可以使 TypeScript 和 Babel 的行为保持一致。

eslint配置

eslintrc记得增加tsconfig.server.json

parserOptions: {
    project: ['./tsconfig.json','./tsconfig.server.json']
},

检查是否可以编写服务端ts文件

如果还是没有ts提示,看看tsconfig的include有没有配置对,需要重启vscode。

配置nodemon运行时编译ts的命令

nodemon是express服务端开发的常用工具配置。
上面的ts类型校验完善后,这时候你会发现我们的项目启动不起来,因为服务器端没有babel给它编译成ts,我们想要在node端实时编译ts,通常需要结合使用 ts-node,它可以在运行时直接编译和执行 TypeScript 文件。

npm i -D ts-node

然后变更nodemon命令,原本是nodemon server/index.js,现在要加上指定命令行以ts-node的形式执行:

nodemon --exec ts-node server/index.js

配置ts文件的build命令

typescript带来的tsc命令可以把ts文件编译成js文件,所以你也可以看到有些demo的build命令直接就是一个tsc,但是因为商业项目中涉及到的其他文件太多,我们往往使用webpack+babel的方案将ts转化成js。

在上面的客户端引入ts中我们已经下载了ts-loader@babel/preset-typescript,也进行了配置,因此我们的build命令仍然正常使用webpack打包就可以了。

但是next的打包是专门提供了一个next build命令,这个命令只适用于next的代码,对于我们自行搭建的express服务器的代码没有办法执行,因此我们额外需要对ts的服务器端配置需要专门指定tsconfig。修改如下:

next build && tsc --project tsconfig.server.json

如何在express中书写ts文件?

不知道大家有没有遇到这个问题:原本的文件都是用CJS导入导出的,但是根本不支持导出type,写个type到处都是报错😭
参考:
利用typescript + express 开发一个nodejs服务端demo

看起来,CJS的type只能写.d.ts文件?
比如:我们可以定义一个custom.d.ts文件,在Request的接口中添加我们加入的属性,这样在使用的时候就会出现提示。custom.d.ts文件会和@types/express里面的类型文件进行合并。

// costom.d.ts
declare namespace Express {
  interface Request {
    teacherName: string
  }
}

但是使用ES6就可以直接导出type,不用声明import type xxx

🌰
// ErrorResponse.ts
export default interface ErrorResponse {
  message: string;
  stack?: string;
}

// index.js
import MessageResponse from '../interfaces/MessageResponse';

router.get<{}, MessageResponse>('/', (req, res) => {
  res.json({
    message: '',
  });
});

好的,我会根据您的要求回答您的问题,以下是从0到1塔建vite+vue3的ssr的服务端渲染的使用方法,不使用ts: 1. 首先,安装Vite和Vue3 ``` npm install -g vite npm install vue@next ``` 2. 创建项目并初始化 ``` mkdir my-ssr-app cd my-ssr-app npm init -y ``` 3. 安装依赖 ``` npm install vue-server-renderer express ``` 4. 创建服务端入口文件 在项目根目录下创建`server.js`文件,并添加以下内容: ```javascript const express = require('express') const { createRenderer } = require('vue-server-renderer') const { createApp } = require('./src/main') const app = express() // 静态资源目录 app.use(express.static('dist')) const renderer = createRenderer() app.get('*', async (req, res) => { const app = createApp() const html = await renderer.renderToString(app) res.end(` <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>SSR Vite Vue 3</title> </head> <body> <div id="app">${html}</div> <script src="/client.js"></script> </body> </html> `) }) app.listen(3000, () => { console.log('Server started at http://localhost:3000') }) ``` 5. 创建客户端入口文件 在项目根目录下创建`src/main.js`文件,并添加以下内容: ```javascript import { createApp } from 'vue' import App from './App.vue' export function createApp () { const app = createApp(App) return { app } } ``` 6. 配置Vite 在项目根目录下创建`vite.config.js`文件,并添加以下内容: ```javascript const { createVuePlugin } = require('vite-plugin-vue2') module.exports = { plugins: [ createVuePlugin() ], build: { ssrManifest: true, outDir: 'dist', rollupOptions: { input: 'src/entry-client.js', output: { format: 'esm', entryFileNames: '[name]-[hash].js' } } }, optimizeDeps: { include: [ 'vue', 'vue-router' ] } } ``` 7. 创建组件 在`src`文件夹下创建`App.vue`文件,并添加以下内容: ```vue <template> <div> <h1>{{ message }}</h1> </div> </template> <script> export default { data () { return { message: 'Hello World!' } } } </script> ``` 8. 运行项目 使用以下命令启动项目: ``` vite build && node server.js ``` 9. 查看效果 在浏览器中访问`http://localhost:3000`,即可看到页面渲染结果。 以上就是从0到1塔建vite+vue3的ssr的服务端渲染的使用方法,不使用ts的步骤。希望对您有所帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值