Hi~,我是 一碗周,一个在舒适区垂死挣扎的前端,如果写的文章有幸可以得到你的青睐,万分有幸~
🍍 写在前面
Nuxt3在今年的4月分发布RC版本,到现在也已经大半年了,估计用不了多久正式版也就该发布了,也该是时候体验一下Nuxt3了。
这个项目模板已经包含了以下的内容
- 🎨 使用Tailwind作为CSS组件库,并安装daisyUI插件,关于daisyUI可以参考:daisyUI快速上手;
- 💪 ESlint和Stylelint代码检验;
- 🐶 创建Git commit message规范校验;
- 🎉 天然支持Vue3、Typescript、Vite等;
- 🍍 集成Pinia作为状态管理;
- 🥤 集成vueuse作为Hooks库;
- 🎊文件式路由、componentsAPI自动导入、组件自动导入等;
这里我使用pnpm作为包管理工具,其版本如下:
- Node:v16.15.0
- pnpm:7.14.2
🍓 安装Nuxt3
由于国内的网络环境访问Github经常挂,这里准备了三种安装方式,准确的说还是一种,只不过由自动变成了手动。
🍕 脚手架方式安装
通过脚手架方式安装也是官网中提供的,命令比较简单,如下所示:
pnpm dlx nuxi init nuxt3-template
这种方式经常会失败,失败后可以多次尝试,如果还不行可以选择下一种;
🧁 直接下载压缩包
第二种方式比较简单粗暴,直接下载脚手架中使用的模板,下载地址【https://codeload.github.com/nuxt/starter/tar.gz/refs/heads/v3】,然后解压就可以了,与第一种方式得到的最终效果是一致的。
🍬 复制粘贴
如果第二种也不能下载的话,可以尝试第三种,就是复制粘贴模板中的代码,这个更无脑,直接依次在根目录下创建下面这些文件并粘贴即可:
package.json
{
"private": true,
"scripts": {
"build": "nuxt build",
"dev": "nuxt dev",
"generate": "nuxt generate",
"preview": "nuxt preview",
"postinstall": "nuxt prepare"
},
"devDependencies": {
"nuxt": "3.0.0-rc.13"
}
}
.gitignore
node_modules
*.log*
.nuxt
.nitro
.cache
.output
.env
dist
app.vue
<template>
<div>
<NuxtWelcome />
</div>
</template>
nuxt.config.ts
// https://v3.nuxtjs.org/api/configuration/nuxt.config
export default defineNuxtConfig({
})
tsconfig.json
{
// https://v3.nuxtjs.org/concepts/typescript
"extends": "./.nuxt/tsconfig.json"
}
🍗 安装依赖
选择自己的包管理工具安装依赖
# yarn
yarn install
# npm
npm install
# pnpm
pnpm install --shamefully-hoist
然后执行pnpm dev
即可看到下面这个页面:
到这我们的第一步就已经完成了。
🍣 规范规范规范
在一个项目中代码检查、统一代码风格肯定是不能少的,我们依次来看:
🥯 ESlint
ESlint是什么我就不多说了,这里我代码格式化也是使用的ESlint,用的是Anthony Fu大佬的ESlint配置,为什么不用Prettier,看看大佬怎么说:
Why I don't use Prettier (antfu.me)
大佬的配置使用给了非常详细的步骤,这里我就在搬一下:
安装依赖:
pnpm i -D eslint @antfu/eslint-config typescript
创建.eslintrc
配置文件,并写入下面这段内容:
{
"extends": "@antfu"
}
创建.vscode/settings.json
配置文件,并写入下面这段内容
{
"prettier.enable": false,
"editor.formatOnSave": false,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
}
}
简单几步就配置完成了,比自己安装各种包要省心的多,也不需要过多的考虑,而且可以轻松的覆盖各种规则。
🌴 Stylelint
这里配置一下Stylelint,用于检测CSS是否规范,虽然这个项目中会安装TailwindCSS但是也不可能一行CSS不写,所以还是需要简单配置一下的。
首先我们安装一下依赖:
pnpm i -D stylelint stylelint-config-standard postcss-html stylelint-config-html stylelint-config-recess-order
stylelint
:核心库stylelint-config-standard
:CSS规范postcss-html
:stylelint-config-html
中依赖这个包stylelint-config-html
:可以格式化HTML、Vue中的style标签中的CSSstylelint-config-recess-order
:调整属性的顺序
安装完依赖后我们需要创建一个style.config.js
文件并写入下面这些内容:
module.exports = {
/* 继承某些已有的规则 */
extends: [
'stylelint-config-standard', // 配置stylelint拓展插件
'stylelint-config-html/vue', // 配置 vue 中 template 样式格式化
'stylelint-config-recess-order', // 配置stylelint css属性书写顺序插件,
],
overrides: [
// 扫描 .vue/html 文件中的<style>标签内的样式
{
files: ['**/*.{vue,html}'],
customSyntax: 'postcss-html',
},
],
rules: {
'string-quotes': 'double', // 指定字符串使用单引号或双引号
'color-hex-case': 'lower', // 16 进制颜色全小写
'color-hex-length': 'long', // 禁止16禁止颜色小写
'rule-empty-line-before': 'always', // 在规则之前的空行必须始终有一个空行
'block-opening-brace-space-before': 'always', // 在块的开大括号之前必须有一个空格
'selector-pseudo-class-no-unknown': [
true,
{
ignorePseudoClasses: ['global', 'v-deep', 'deep'],
},
],
},
}
然后在.vscode/settings.json
配置文件加入下面几行内容
{
"prettier.enable": false,
"editor.formatOnSave": false,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true,
"source.fixAll.stylelint": true
},
+ "stylelint.enable": true,
+ "stylelint.validate": [
+ "css",
+ "vue",
+ "html"
+ ]
}
到这Stylelint也配置完成了。
🥒 Git提交验证
接下来是Git commit message规范以及在提交前对代码进行检查的配置,首先安装依赖:
pnpm i -D husky
创建.husky
文件夹
pnpm husky install # 前提是已经初始化Git仓库
安装lint-staged
依赖,用于检测本地暂存代码:
pnpm i -D lint-staged
在package.json
中加入下面这段内容:
{
"scripts": {
"lint-staged": "lint-staged",
},
"lint-staged": {
"*.{js,ts,tsx,jsx}": [
"eslint --fix --ext"
],
"*.vue": [
"eslint --fix --ext",
"stylelint --cache --fix"
],
"*.{css,html}": [
"stylelint --cache --fix"
]
}
}
创建git commit
钩子,让其执行lint-staged
脚本,执行命令如下:
pnpm husky add .husky/pre-commit "pnpm lint-staged"
最后配置校验commit信息,首先安装依赖:
pnpm i -D @commitlint/cli @commitlint/config-conventional commitizen cz-git
# @commitlint/cli @commitlint/config-conventional: commit规范以及校验工具
# commitizen: 用于生成message的包
# cz-git: commitizen 适配器
首先指定适配器,修改package.json
添加config
:
{
"scripts": {
},
"config": {
"commitizen": {
"path": "node_modules/cz-git"
}
}
}
然后添加commit msg钩子,并执行指定命令:
pnpm husky add .husky/commit-msg 'pnpm commitlint --edit'
最后添加我们提交的自定义配置,在根目录创建commitlint.config.js
,并写入下面这段内容:
// @see: https://cz-git.qbenben.com/zh/guide
/** @type {import('cz-git').UserConfig} */
module.exports = {
ignores: [commit => commit.includes('init')],
extends: ['@commitlint/config-conventional'],
rules: {
// @see: https://commitlint.js.org/#/reference-rules
'body-leading-blank': [2, 'always'],
'footer-leading-blank': [1, 'always'],
'header-max-length': [2, 'always', 108],
'subject-empty': [2, 'never'],
'type-empty': [2, 'never'],
'subject-case': [0],
'type-enum': [
2,
'always',
[
'feat',
'fix',
'docs',
'style',
'refactor',
'perf',
'test',
'build',
'ci',
'chore',
'revert',
'wip',
'workflow',
'types',
'release',
],
],
},
prompt: {
messages: {
// type: 'Select the type of change that you're committing:',
// scope: 'Denote the SCOPE of this change (optional):',
// customScope: 'Denote the SCOPE of this change:',
// subject: 'Write a SHORT, IMPERATIVE tense description of the change:\n',
// body: 'Provide a LONGER description of the change (optional). Use "|" to break new line:\n',
// breaking: 'List any BREAKING CHANGES (optional). Use "|" to break new line:\n',
// footerPrefixsSelect: 'Select the ISSUES type of changeList by this change (optional):',
// customFooterPrefixs: 'Input ISSUES prefix:',
// footer: 'List any ISSUES by this change. E.g.: #31, #34:\n',
// confirmCommit: 'Are you sure you want to proceed with the commit above?',
// 中文版
type: '选择你要提交的类型 :',
scope: '选择一个提交范围(可选):',
customScope: '请输入自定义的提交范围 :',
subject: '填写简短精炼的变更描述 :\n',
body: '填写更加详细的变更描述(可选)。使用 "|" 换行 :\n',
breaking: '列举非兼容性重大的变更(可选)。使用 "|" 换行 :\n',
footerPrefixsSelect: '选择关联issue前缀(可选):',
customFooterPrefixs: '输入自定义issue前缀 :',
footer: '列举关联issue (可选) 例如: #31, #I3244 :\n',
confirmCommit: '是否提交或修改commit ?',
},
types: [
// 英文
// { value: 'feat', name: 'feat: 🚀 A new feature', emoji: '🚀' },
// { value: 'fix', name: 'fix: 🧩 A bug fix', emoji: '🧩' },
// { value: 'docs', name: 'docs: 📚 Documentation only changes', emoji: '📚' },
// { value: 'style', name: 'style: 🎨 Changes that do not affect the meaning of the code', emoji: '🎨' },
// { value: 'refactor', name: 'refactor: ♻️ A code change that neither fixes a bug nor adds a feature', emoji: '♻️' },
// { value: 'perf', name: 'perf: ⚡️ A code change that improves performance', emoji: '⚡️' },
// { value: 'test', name: 'test: ✅ Adding missing tests or correcting existing tests', emoji: '✅' },
// { value: 'build', name: 'build: 📦️ Changes that affect the build system or external dependencies', emoji: '📦️' },
// { value: 'ci', name: 'ci: 🎡 Changes to our CI configuration files and scripts', emoji: '🎡' },
// { value: 'chore', name: 'chore: 🔨 Other changes that don't modify src or test files', emoji: '🔨' },
// { value: 'revert', name: 'revert: ⏪️ Reverts a previous commit', emoji: '⏪️' },
// 中文版
// { value: '特性', name: '特性: 🚀 新增功能', emoji: '🚀' },
// { value: '修复', name: '修复: 🧩 修复缺陷', emoji: '🧩' },
// { value: '文档', name: '文档: 📚 文档变更', emoji: '📚' },
// { value: '格式', name: '格式: 🎨 代码格式(不影响功能,例如空格、分号等格式修正)', emoji: '🎨' },
// { value: '重构', name: '重构: ♻️ 代码重构(不包括 bug 修复、功能新增)', emoji: '♻️' },
// { value: '性能', name: '性能: ⚡️ 性能优化', emoji: '⚡️' },
// { value: '测试', name: '测试: ✅ 添加疏漏测试或已有测试改动', emoji: '✅' },
// { value: '构建', name: '构建: 📦️ 构建流程、外部依赖变更(如升级 npm 包、修改 webpack 配置等)', emoji: '📦️' },
// { value: '集成', name: '集成: 🎡 修改 CI 配置、脚本', emoji: '🎡' },
// { value: '回退', name: '回退: ⏪️ 回滚 commit', emoji: '⏪️' },
// { value: '其他', name: '其他: 🔨 对构建过程或辅助工具和库的更改(不影响源文件、测试用例)', emoji: '🔨' },
// 中英混合版
{ value: 'feat', name: 'feat: 🚀 新增功能', emoji: '🚀' },
{ value: 'fix', name: 'fix: 🧩 修复缺陷', emoji: '🧩' },
{ value: 'docs', name: 'docs: 📚 文档变更', emoji: '📚' },
{ value: 'style', name: 'style: 🎨 代码格式(不影响功能,例如空格、分号等格式修正)', emoji: '🎨' },
{ value: 'refactor', name: 'refactor: ♻️ 代码重构(不包括 bug 修复、功能新增)', emoji: '♻️' },
{ value: 'perf', name: 'perf: ⚡️ 性能优化', emoji: '⚡️' },
{ value: 'test', name: 'test: ✅ 添加疏漏测试或已有测试改动', emoji: '✅' },
{ value: 'build', name: 'build: 📦️ 构建流程、外部依赖变更(如升级 npm 包、修改 webpack 配置等)', emoji: '📦️' },
{ value: 'ci', name: 'ci: 🎡 修改 CI 配置、脚本', emoji: '🎡' },
{ value: 'revert', name: 'revert: ⏪️ 回滚 commit', emoji: '⏪️' },
{ value: 'chore', name: 'chore: 🔨 对构建过程或辅助工具和库的更改(不影响源文件、测试用例)', emoji: '🔨' },
],
useEmoji: true,
themeColorCode: '',
scopes: [],
allowCustomScopes: true,
allowEmptyScopes: true,
customScopesAlign: 'bottom',
customScopesAlias: 'custom',
emptyScopesAlias: 'empty',
upperCaseSubject: false,
allowBreakingChanges: ['feat', 'fix'],
breaklineNumber: 100,
breaklineChar: '|',
skipQuestions: [],
issuePrefixs: [{ value: 'closed', name: 'closed: ISSUES has been processed' }],
customIssuePrefixsAlign: 'top',
emptyIssuePrefixsAlias: 'skip',
customIssuePrefixsAlias: 'custom',
allowCustomIssuePrefixs: true,
allowEmptyIssuePrefixs: true,
confirmColorize: true,
maxHeaderLength: Infinity,
maxSubjectLength: Infinity,
minSubjectLength: 0,
scopeOverrides: undefined,
defaultBody: '',
defaultIssues: '',
defaultScope: '',
defaultSubject: '',
},
}
到这为止关于代码规范部分就已经全部完成了。
👹 依赖的安装与配置
🎨 TailwindCSS
我们先在项目中安装一下TailwindCSS,这里使用的是Nuxt版本,安装命令如下:
pnpm i -D @nuxtjs/tailwindcss
然后在nuxt.config.ts
中加入一行内容:
export default defineNuxtConfig({
+ modules: ['@nuxtjs/tailwindcss'],
})
其实到这就已经可以在项目中使用了,@nuxtjs/tailwindcss
中为很多配置都增加了默认值,也就省去我们自己去配置了。
当然,自己配置也可以,在nuxt.config.ts
中添加一个tailwindcss
配置项,然后可以自己配置,具体参考Options | Nuxt Tailwind (nuxtjs.org)
🍵 daisyUI
这里我们使用daisyUI
作为我们的组件库,安装比较简单,命令如下:
如果你对daisyUI不了解,可以看我另一篇文章 daisyUI快速上手,解决TailwindCSS疯狂堆砌class的问题
pnpm i daisyui
然后,在根目录创建tailwind.config.js
并写入下面这段内容:
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [],
theme: {
extend: {},
},
plugins: [require('daisyui')], // 以插件的方式引入
}
都设置完成后我们随便写点东西来看一下效果:
app.vue
<template>
<div class="min-h-screen hero" :style="{ backgroundImage: 'url(https://placeimg.com/1000/800/arch)' }">
<div class="bg-opacity-60 hero-overlay" />
<div class="text-center hero-content text-neutral-content">
<div class="max-w-md">
<h1 class="mb-5 text-5xl font-bold">
Hello there
</h1>
<p class="mb-5">
Provident cupiditate voluptatem et in. Quaerat fugiat ut assumenda excepturi exercitationem quasi. In deleniti eaque aut repudiandae et a id nisi.
</p>
<button class="btn btn-primary">
Get Started
</button>
</div>
</div>
</div>
</template>
现在运行我们的项目
pnpm dev
打开浏览器即可看到下面这个页面:
🥨 与ESlint配合
使用TailwindCSS存在一个问题,就是类名的顺序不固定,导致后期维护起来有些许困难,我们可以安装一个ESlint的插件eslint-plugin-tailwindcs
来解决这个问题,这个插件的主要作用是调整类名的顺序,使用步骤如下:
首先安装依赖:
pnpm i -D eslint-plugin-tailwindcss
然后在.eslintrc
中加入下面这几行:
{
"plugins": [
"tailwindcss"
],
"extends": [
"plugin:tailwindcss/recommended",
"@antfu"
]
}
然后在保存时就可以自动格式化代码了。
这里需要注意一下,我的tailwindcss
的版本是3.2,在写这篇文章的时候使用eslint-plugin-tailwindcss@3.6.2
无法格式化,我安装的是tailwindcss@3.5.2
,可以正常格式化。
🍍 Pinia
现在我们安装Pinia,命令如下:
pnpm install @pinia/nuxt
然后在nuxt.config.ts
中增加配置配置文件:
export default defineNuxtConfig({
modules: [
'@nuxtjs/tailwindcss',
+ '@pinia/nuxt',
],
})
到这就配置完了,就可以在项目中直接使用了。
🐰 vueuse
vueuse
作为Vue的Hooks库,库中封装了很多好用的函数,这里就不展开了介绍了。
在Nuxt3
中安装比较简单,仅需两步:
首先安装依赖
npm i -D @vueuse/nuxt @vueuse/core
然后在nuxt.config.ts
中添加配置:
// nuxt.config.ts
export default {
modules: [
'@vueuse/nuxt',
],
}
export default defineNuxtConfig({
modules: [
'@nuxtjs/tailwindcss',
'@pinia/nuxt',
+ '@vueuse/nuxt',
],
})
现在就配置完成了,如果想要测试是否安装成功可以在app.vue
中写入下面这段代码:
<script setup>
useHead({
title: 'nuxt3-template',
link: [
{
rel: 'icon', type: 'image/png', href: '/nuxt.png',
},
],
})
</script>
然后就可以看到我们的网站的标题以及icon都发生了变化。
🍇 写在最后
本篇文章到这就结束了,在这篇文章中介绍了Nuxt3项目的搭建过程,Github地址:ywanzhou/nuxt3-template: Nuxt3的一个开箱即用的模板 (github.com),喜欢可以点一个star支持一下。