nuxt+typescript项目搭建

4,987 阅读4分钟

nuxt+typescript项目搭建

使用nuxt已经遇到很多坑了,本来是有整理nuxt的采坑的,但是相关文章也很多就跳过了。主要是针对ts,没有找到一篇符合我心意的文章。介怀没有ts这种强类型的判断,故搞之。其实针对ts,nuxt是有ts文档

Nuxt官网地址奉上

题外话:文档终于在2.8之后更新了。但我写这个文章的时候nuxt已经到2.10了。我就是想吐槽一下很多东西都还只能issue里面翻。有很多坑来自于版本更新迭代。此时就不费精力去手动创建项目了,用官方脚手架。

1. 基于脚手架,启动一个nuxt项目

  • Nuxt.js团队创建了脚手架工具 create-nuxt-app。
  • 确保安装了npx(npx在NPM版本5.2.0默认安装了)

确保了上面这2点再进行指令好吗?当然也可以选官方指导

1.1. 脚手架指令搭建项目
// 创建项目,nuxt-ts 为项目名
npx create-nuxt-app nuxt-ts

1.2. 配置选择

你可以能会根据自己的情况选择所需配置,我的选择如下:


create-nuxt-app v2.11.1
✨  Generating Nuxt.js project in nuxt-ts
? Project name nuxt-ts
? Project description My majestic Nuxt.js project
? Author name collin
? Choose the package manager Yarn
? Choose UI framework None
? Choose custom server framework Koa
? Choose Nuxt.js modules Axios
? Choose linting tools ESLint, Prettier
? Choose test framework None
? Choose rendering mode Universal (SSR)
? Choose development tools jsconfig.json (Recommended for VS Code)
1.3. 项目运行与打包
// 类似npm run dev,我使用的yarn故
cd nuxt-ts
yarn dev

// 打包+运行(这个一般是部署所用,当然也可以本地运行):
cd nuxt-ts
yarn build
yarn start

ok,到此,借助脚手架,已经有了项目的雏形了。Let's go on

2. 借助vscode插件【Version Lens】把依赖项全升级成最新版

如果觉得下载太慢,可以在根目录新建.yarnrc文件,指定下载源

// .yarnrc
registry "https://registry.npm.taobao.org"
sass_binary_site "https://npm.taobao.org/mirrors/node-sass/"
phantomjs_cdnurl "http://cnpmjs.org/downloads"
electron_mirror "https://npm.taobao.org/mirrors/electron/"
sqlite3_binary_host_mirror "https://foxgis.oss-cn-shanghai.aliyuncs.com/"
profiler_binary_host_mirror "https://npm.taobao.org/mirrors/node-inspector/"
chromedriver_cdnurl "https://cdn.npm.taobao.org/dist/chromedriver"
// package.json
"dependencies": {
    "nuxt": "^2.10.2",
    "cross-env": "^6.0.3",
    "koa": "^2.11.0",
    "@nuxtjs/axios": "^5.8.0"
},
"devDependencies": {
    "nodemon": "^1.19.4",
    "@nuxtjs/eslint-config": "^1.1.2",
    "@nuxtjs/eslint-module": "^1.1.0",
    "babel-eslint": "^10.0.3",
    "eslint": "^6.6.0",
    "eslint-plugin-nuxt": ">=0.4.3",
    "eslint-config-prettier": "^6.5.0",
    "eslint-plugin-prettier": "^3.1.1",
    "prettier": "^1.19.0"
}

yarn dev 保证项目正常运行


3. 支持ts写法

参考官方文档

修改js文件为ts文件(包括引用的地方)

  • jsconfig.json --> tsconfig.json
  • nuxt.config.js --> nuxt.config.ts
  • server/index.js --> server/index.ts(改为引用nuxt.config.ts)
  • package.json中的dev,和start指令 .js --> .ts
  • 根目录新增 global.d.ts(全局声明)
  • 根目录新增 shims-tsx.d(在Vue项目中编写jsx代码)
  • 根目录新增 shims-vue.d(TypeScript 识别.vue 文件)
3.1. 安装ts插件
// 2.8版本:
yarn remove @nuxt/typescript
yarn add @nuxt/typescript-build

yarn add @nuxt/typescript-runtime 【运行时】

// 如果没有安装ts-node,则安装即可
3.2 添加 @nuxt/typescript-build 到配置文件nuxt.config.ts
// nuxt.config.js
export default {
  buildModules: ['@nuxt/typescript-build']
}

3.3 tsconfig.json中,用 @nuxt/types 替换 @nuxt/vue-app 和 @nuxt/config
// tsconfig.json
// tsconfig 还有很多‘好玩’的配置,各位好好挖掘啊!以下是官方基本配置,新增了types
{
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    "moduleResolution": "node",
    "lib": [
      "esnext",
      "esnext.asynciterable",
      "dom"
    ],
    "esModuleInterop": true,
    "allowJs": true,
    "sourceMap": true,
    "strict": true,
    "noEmit": true,
    "baseUrl": ".",
    "paths": {
      "~/*": [
        "./*"
      ],
      "@/*": [
        "./*"
      ]
    },
    "types": [
      "@types/node",
      "@nuxt/types" // 新增
    ]
  },
  "exclude": [
    "node_modules"
  ]
}

如果要从@ nuxt/config导入类型,则需要从 @nuxt/types 导入它们。

3.4. 将自定义选项从build.typescript移动到模块选项
// nuxt.config.js
export default {
  buildModules: [
    ['@nuxt/typescript-build', {
      typeCheck: true,
      ignoreNotFoundWarnings: true
    }]
  ]
}
3.5. package.json(使用nuxt-ts运行)
"scripts": {
  "dev": "nuxt-ts",
  "build": "nuxt-ts build",
  "generate": "nuxt-ts generate",
  "start": "nuxt-ts start"
},
"dependencies": {
  "@nuxt/typescript-runtime",
  "nuxt"
},
"devDependencies": {
  "@nuxt/typescript-build"
}

4. 安装tslint,

4.1 安装@typescript-eslint/eslint-plugin
yarn add @typescript-eslint/eslint-plugin
4.2 配置.eslintrc.js

我更喜欢使用eslint-plugin-vue来处理vue中‘html’的格式问题。(这个随个人,相关依赖插件不要忘记安装)

// .eslintrc.js
parserOptions: {
    // parser: 'babel-eslint'
    parser: '@typescript-eslint/parser'
},
extends: [
    '@nuxtjs',
    'prettier',
    'prettier/vue',
    // 'plugin:prettier/recommended',
    'plugin:vue/recommended',
    'plugin:nuxt/recommended'
],
plugins: [
    'vue',
    '@typescript-eslint'
],
rules: {
    // 还是用官方的 eslint-plugin-vue 配置.vue文件的html报错吧...
    'nuxt/no-cjs-in-config': 'off',
    'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
    'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
    'vue/html-indent': 0,
    'vue/max-attributes-per-line': 0,
    "vue/html-closing-bracket-newline": 0,
    'vue/attributes-order': 0,
    'vue/name-property-casing': 0,
    'vue/html-self-closing': 0,
    'vue/no-parsing-error': [0, {
      'x-invalid-end-tag': false
    }],
    'vue/mustache-interpolation-spacing': 0,
    'vue/attribute-hyphenation': 0,
    'vue/require-valid-default-prop': 0,
    'vue/require-default-prop': 0,
    'vue/require-prop-types': 0,
    "vue/no-unused-components": 0,
    "vue/singleline-html-element-content-newline": 0,
    "vue/multiline-html-element-content-newline": 0,
    "vue/order-in-components": 0,
    "vue/no-dupe-keys": 0,
    //...
}

5. 使用ts装饰器

其实到此为止已经可以使用了,如果你喜欢装饰器写法,则可以试试。

yarn add vue-property-decorator vuex-class
// 写法将变成这样
<script lang="ts">
  import {Component, Vue} from 'vue-property-decorator'
  import {State, Getter} from 'vuex-class'

  @Component({})
  export default class IndexPage extends Vue {
    // 原data
    testMsg = 'My splendiferous Nuxt.js project'
    // 计算属性
    private get computedVal(): string {
      return `computedVal: ${this.testMsg} `
    }
    // Vuex 数据
    @State(state => state.userInfo) vxUserInfo
    // 生命周期
    private created(): void {}
    // method
    public init(): void {}
  }
</script>

6. 装个UI库,弥补前面没有装插件这个流程

6.1 以 vant UI为例吧
yarn add vant -S
6.2 plugin下新建vant/index.js
// vant/index.js
import Vue from "vue";
import Vant from "vant";
import 'vant/lib/index.css'; // 通过nuxt.config.ts中css: ['vant/lib/index.css']配置也行

export default () => {
  Vue.use(Vant);
}
6.3 对 vant 进行配置(flexible + postcss-px2rem-exclude)
  1. 使用 flexible,设置html的 font-size
# static/flexible/index.js

!function(e,t){function n(){t.body?t.body.style.fontSize=12*o+"px":t.addEventListener("DOMContentLoaded",n)}function d(){var e=i.clientWidth/10;i.style.fontSize=e+"px"}var i=t.documentElement,o=e.devicePixelRatio||1;if(n(),d(),e.addEventListener("resize",d),e.addEventListener("pageshow",function(e){e.persisted&&d()}),o>=2){var a=t.createElement("body"),s=t.createElement("div");s.style.border=".5px solid transparent",a.appendChild(s),i.appendChild(a),1===s.offsetHeight&&i.classList.add("hairlines"),i.removeChild(a)}}(window,document);
// nuxt.config.ts 
header: {
  script: [{
      src: '/flexible/flexible.js',
      type: 'text/javascript',
      charset: 'utf-8',
  }]
}
  1. postcss-px2rem-exclude,排除vant【vant已经使用rem了】
yarn add postcss-px2rem-exclude
// nuxt.config.ts
plugins: [
    {src: '~/plugins/vant', ssr: true},
],
build:
    postcss: {
      plugins: {
        'postcss-px2rem-exclude': {
          remUnit: 75, // 转换基本单位
          exclude: /vant/i,
        },
      },
      preset: {
        autoprefixer: {
          grid: true,
        },
      },
    },
}
  1. vant主题配置 官网
// 新建覆盖官方样式的less文件
./assets/style/theme/index.less
// nuxt.config.ts
const path = require('path')

extend(config, ctx) {
  if (ctx.isDev && ctx.isClient) {
    config.module.rules.push(
      {
        test: /\.ts$/,
        exclude: [/node_modules/, /vendor/, /\.nuxt/],
        loader: 'ts-loader',
        options: {
          appendTsSuffixTo: [/\.vue$/],
          transpileOnly: true,
        },
      },
      // 新增主题覆盖配置
      {
        test: /\.less$/,
        use: [
          {
            loader: 'less-loader',
            options: {
              modifyVars: {
                // 直接覆盖变量
                // '@blue': '#3EB7E7',
                // 使用外部.less文件覆盖
                'hack': `true; @import "${path.join(__dirname, './assets/style/theme/index.less"')};`
              },
            },
          },
        ],
      },
    )
  }
},

7. Auth Module

官方Auth Module 手册

7.1 安装
yarn add @nuxtjs/auth @nuxtjs/axios -S
7.2 配置nuxt.config.ts
modules: [
    // Doc: https://axios.nuxtjs.org/usage
    '@nuxtjs/axios',
    '@nuxtjs/auth',
],
auth: {
    strategies: {
      local: {
        endpoints: {
          login: {url: '/api/login', method: 'post', propertyName: 'data.token'}, // 登录
          logout: {url: '/api/logout', method: 'post'}, // 登出
          user: {url: '/api/profile', method: 'get', propertyName: 'data'}, // 获取个人信息
        },
        tokenRequired: true, // 是否带上认证
        tokenType: false, // 是否认证添加Bearer
      },
    },
},
7.3 登录
// login.vue
public async login() {
  await this.$auth
    .loginWith('local', {
      data: {
        email: this.email,
        password: this.password,
      },
    })
    .then(() => {
      this.$toast({
        message: this.$auth.user.email,
      })
    })
}

先这样吧~