nuxt+typescript项目搭建
使用nuxt已经遇到很多坑了,本来是有整理nuxt的采坑的,但是相关文章也很多就跳过了。主要是针对ts,没有找到一篇符合我心意的文章。介怀没有ts这种强类型的判断,故搞之。其实针对ts,nuxt是有ts文档的
题外话:文档终于在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)
- 使用 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',
}]
}
- 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,
},
},
},
}
- 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,
})
})
}
先这样吧~