安装

  1. yarn create nuxt-app <项目名>

它会让你进行一些选择:

  1. 项目名称
  2. 选择语言 TS/JS
  3. 选择包管理器 Yarn/Npm
  4. 选择UI框架image.png
  5. 选择nuxtjs模块image.png

  6. 选择lint工具image.png

  7. 选择测试框架image.png
  8. 渲染模式image.png
  9. 部署方式image.png

静态部署:全部路径被打包出 index.html a.html b.html 等文件,而实际访问,服务器就把这些文件服务出去,属于是文件服务。
服务端渲染部署:请求会经过 Node.js express/koa等框架 的 render ,如果你想,它会动态改变,因为是拼接的。

  1. 部署工具image.png
  2. 持续集成image.png
  3. 版本控制系统image.png

image.png

当运行完时,它将安装所有依赖项,因此下一步是启动项目

  1. cd <project-name>
  2. yarn dev

image.png

image.png

目录结构

Nuxt.js 的默认应用目录架构提供了良好的代码分层结构,适用于开发或大或小的应用。当然,你也可以根据自己的偏好组织应用代码。

assets 资源目录

资源目录 assets 用于组织未编译的静态资源如 LESSSASSJavaScript

static 静态文件目录

静态文件目录 static 用于存放应用的静态文件,此类文件不会被 Nuxt.js 调用 Webpack 进行构建编译处理。服务器启动的时候,该目录下的文件会映射至应用的根路径 / 下。

举个例子: /static/robots.txt 映射至 /robots.txt

若无额外配置,该目录不能被重命名。

components 组件目录

组件目录 components 用于组织应用的 Vue.js 组件。Nuxt.js 不会扩展增强该目录下 Vue.js 组件,即这些组件不会像页面组件那样有 asyncData 方法的特性。

layouts 布局目录

布局目录 layouts 用于组织应用的布局组件。

若无额外配置,该目录不能被重命名。

pages 页面目录

页面目录 pages 用于组织应用的路由及视图。Nuxt.js 框架读取该目录下所有的 .vue 文件并自动生成对应的路由配置。

若无额外配置,该目录不能被重命名。

.vue 文件必须小写开头,否则服务自动生成对应路由配置
image.png

middleware 中间件目录

middleware 目录用于存放应用的中间件。

plugins 插件目录

插件目录 plugins 用于组织那些需要在 根 vue.js 应用 实例化之前需要运行的 Javascript 插件。

Store 目录

store 目录用于组织应用的 Vuex 状态树 文件。 Nuxt.js 框架集成了 Vuex 状态树 的相关功能配置,在 store 目录下创建一个 index.js 文件可激活这些配置。

若无额外配置,该目录不能被重命名。

关于 store 的更多信息

nuxt.config.js 文件

nuxt.config.js 文件用于组织 Nuxt.js 应用的个性化配置,以便覆盖默认配置。

若无额外配置,该文件不能被重命名。

关于 nuxt.config.js 的更多信息

package.json 文件

package.json 文件用于描述应用的依赖关系和对外暴露的脚本接口。

该文件不能被重命名。

路径别名

别名 目录
~
@
srcDir
~~
@@
rootDir

默认情况下,srcDirrootDir 相同。

提示: 在您的 vue 模板中, 如果你需要引入 assets 或者 static 目录, 使用 ~/assets/your_image.png~/static/your_image.png方式。

项目基础依赖配置

git cz

git cz 相当于是一个对于 git commit 的提交命令的规范化工具,使 git commit 提交规范化。

直接写commit 命令,feat、fix 等提交类型有可能写错导致提交不规范

  1. git commit -m 'feat: add list '
  • feat:新功能(feature)
  • fix:修补bug
  • docs:文档(documentation)只是文档的更改
  • style: 格式(不影响代码运行的变动,例如空格、格式化、少了分号等等)
  • refactor:重构(即不是新增功能,也不是修改bug的代码变动)
  • test:增加测试
  • chore:构建过程或辅助工具的变动
  • perf:提高性能的代码提交
  • revert: 撤回提交
  • test:添加或修正测试

git cz 工具可以直接选择提交类型,不容易出错
image.png

  1. git cz
  2. cz-cli@4.2.3, cz-conventional-changelog@3.3.0
  3. #指定commit的类型,约定了feat、fix两个主要type,以及docs、style、build、refactor、revert五个特殊type
  4. ? **Select the type of change that you're committing:** fix: A bug fix
  5. #用于描述改动的范围,格式为项目名/模块名
  6. ? **What is the scope of this change (e.g. component or file name): (press enter t**
  7. **o skip)** index.html
  8. #对改动进行简短的描述
  9. ? **Write a short, imperative tense description of the change (max 83 chars):**
  10. (11) add a blank
  11. #对改动进行长的描述
  12. ? **Provide a longer description of the change: (press enter to skip)**
  13. #是破坏性的改动吗
  14. ? **Are there any breaking changes?** No
  15. #影响了哪个issue吗,如果选是,接下来要输入issue号
  16. ? **Does this change affect any open issues?** No
  1. yarn add cz-conventional-changelog@3.3.0 -D

安装完之后在 package.json 添加如下命令:

  1. "config": {
  2. "commitizen": {
  3. "path": "./node_modules/cz-conventional-changelog"
  4. }
  5. }

image.png

tsconfig.js

image.png

  1. {
  2. "compilerOptions": {
  3. "target": "ES2018",
  4. "module": "ESNext",
  5. "moduleResolution": "Node",
  6. "jsx": "preserve",
  7. "noImplicitAny": false,
  8. "lib": ["ESNext", "ESNext.AsyncIterable", "DOM"],
  9. "esModuleInterop": true,
  10. "allowJs": true,
  11. "sourceMap": true,
  12. "strict": true,
  13. "noEmit": true,
  14. "experimentalDecorators": true,
  15. "baseUrl": ".",
  16. "paths": {
  17. "~/*": ["./*"],
  18. "@/*": ["./*"]
  19. },
  20. "types": ["@nuxt/types", "@nuxtjs/axios", "@nuxt/content", "@types/node"]
  21. },
  22. "exclude": ["node_modules", ".nuxt", "dist"]
  23. }

Eslint 校验 js 代码

安装 eslint-plugin-prettier

  1. yarn add eslint-plugin-prettier --dev

.eslintrc.js

  1. module.exports = {
  2. root: true,
  3. env: {
  4. browser: true,
  5. node: true
  6. },
  7. parserOptions: {
  8. ecmaVersion: 2020
  9. },
  10. extends: [
  11. '@nuxtjs/eslint-config-typescript',
  12. 'plugin:nuxt/recommended',
  13. 'plugin:prettier/recommended'
  14. ],
  15. plugins: [],
  16. // add your custom rules here
  17. rules: {}
  18. }

image.png

Stylelint 校验 css 代码

Tutorial.vue 尝试加入css,stylelint检测正常
image.png
image.png
项目使用less预处理器,stylelint检测失效
image.png

  1. yarn add -D postcss-less

stylelint.config.js 中注释或者移除一下代码

  1. // customSyntax: 'postcss-html',

否则less文件vscode不会报错
image.png

安装 stylelint-order

  1. yarn add stylelint-order --dev
  1. module.exports = {
  2. customSyntax: "postcss-html",
  3. extends: [
  4. "stylelint-config-standard",
  5. "stylelint-config-recommended-vue",
  6. // "stylelint-config-prettier",
  7. ],
  8. plugins: ["stylelint-order"],
  9. // add your custom config here
  10. // https://stylelint.io/user-guide/configuration
  11. rules: {},
  12. };

image.png
添加自定义规则

  1. rules: {
  2. 'at-rule-no-unknown': null,
  3. 'font-family-no-missing-generic-family-keyword': null,
  4. 'declaration-block-trailing-semicolon': null,
  5. 'selector-pseudo-element-colon-notation': null,
  6. 'font-family-name-quotes': null,
  7. 'declaration-colon-newline-after': null,
  8. 'string-quotes': 'single',
  9. 'property-no-vendor-prefix': null
  10. }

image.png

Prettier 格式化代码

修改.prettierrc

  1. {
  2. "printWidth": 100, // 超过最大值换行
  3. "tabWidth": 2, // 缩进字节数
  4. "useTabs": false, // 缩进不使用tab,使用空格
  5. "semi": false, // 末尾不加尾号
  6. "singleQuote": true, // 默认单引号
  7. "quoteProps": "as-needed", // 仅在需要时在对象属性添加引号
  8. "jsxSingleQuote": false, // jsx中使用单引号代替双引号
  9. "trailingComma": "none", // es5对象属性最后加逗号。none不加
  10. "bracketSpacing": true, // 在对象,数组括号与文字之间加空格
  11. "jsxBracketSameLine": false, // jsx中把'>' 是否单独放一行
  12. "arrowParens": "always", // 箭头函数参数只有一个时是否要有小括号
  13. "htmlWhitespaceSensitivity": "ignore", // HTML空白灵敏度,空格被认为是不敏感的
  14. "vueIndentScriptAndStyle": false, // scriptstyle标签不缩进
  15. "endOfLine": "auto",
  16. // 覆写默认配置,为某些特定文件制定特定配置
  17. "overrides": [
  18. {
  19. "files": "*.json",
  20. "options": {
  21. "printWidth": 200
  22. }
  23. }
  24. ]
  25. }

.prettierrc 中设置的单引号等规则未生效,编辑器报错
image.png
需要去掉配置后的说明注释

  1. {
  2. "printWidth": 100,
  3. "tabWidth": 2,
  4. "useTabs": false,
  5. "semi": false,
  6. "singleQuote": true,
  7. "quoteProps": "as-needed",
  8. "jsxSingleQuote": false,
  9. "trailingComma": "none",
  10. "bracketSpacing": true,
  11. "jsxBracketSameLine": false,
  12. "arrowParens": "always",
  13. "htmlWhitespaceSensitivity": "ignore",
  14. "vueIndentScriptAndStyle": false,
  15. "endOfLine": "auto",
  16. "overrides": [
  17. {
  18. "files": "*.json",
  19. "options": {
  20. "printWidth": 200
  21. }
  22. }
  23. ]
  24. }

配置生效,保存时自动格式化
image.png

image.png

git 提交时 eslint、prettier、stylelint、tsconfig配置修改时,发现未通过 commitlint 工具的校验

  1. yarn lintfix

lint一下发现 .prettierrc中最后一行需换行
image.png

less 预处理器

安装指定版本,不带版本号默认安装最新版,可能会出错

  1. yarn add less@3.0.4 less-loader@5.0.0 -D

package.json
image.png
image.png3
引入全局 less 样式

  1. css: [
  2. 'element-ui/lib/theme-chalk/index.css',
  3. '@/assets/styles/global.less',
  4. ],

这个时候全局样式已经生效,在组件内也可以使用 less

  1. <style lang="less" scoped>
  2. @prefix-cls: ~'basic-footer';
  3. .@{prefix-cls}__qrcode {
  4. width: 5.8rem;
  5. height: 5.8rem;
  6. }
  7. <style>

但是使用全局less文件中声明的 less 变量还是报错

nuxtjs 可以使用 style-resources 自动化导入文件(用于颜色、变量、mixin……)

  1. yarn add @nuxtjs/style-resources --dev
  1. buildModules: [
  2. '@nuxtjs/style-resources',
  3. ],
  4. styleResources: {
  5. less: './assets/global.less'
  6. }

注意:styleResources 配置的资源路径不能使用 ~ 和 @,要使用绝对或者相对路径

组件中使用

  1. p.@{prefix-cls}__company-name {
  2. color: @text-color-inverse;
  3. opacity: 1;
  4. }

pwa

nuxt.config.js 中添加以下配置

  1. pwa: {
  2. manifest: {
  3. name: '关河智图',
  4. short_name: '关河智图',
  5. lang: 'zh-CN'
  6. },
  7. icon: { cacheDir: '/icon.png' },
  8. workbox: {
  9. config: { modulePathPrefix: '/workbox-5.1.4' }
  10. }
  11. },
  12. modules: ["@nuxtjs/pwa"]

在静态static目录中添加icon.png图片文件(512 X 512)

Element UI按需引入

  1. Element-UI 开启按需引入,必须安装 babel-plugin-component 插件

    1. yarn add babel-plugin-component --dev
  2. 安装完成后,在文件根目录创建(或已经存在) plugins/ 目录下创建相应的插件文件,创建名为:element-ui.js 的文件

  1. import Vue from 'vue'
  2. import locale from 'element-ui/lib/locale/lang/zh-CN'
  3. import {
  4. Icon,
  5. Container,
  6. Header,
  7. Aside,
  8. Main,
  9. Menu,
  10. MenuItem,
  11. Button,
  12. Form,
  13. FormItem,
  14. Input,
  15. Row,
  16. Col,
  17. Carousel,
  18. CarouselItem,
  19. Popover
  20. } from 'element-ui'
  21. const Element = {
  22. install(Vue) {
  23. ;[
  24. Icon,
  25. Container,
  26. Header,
  27. Aside,
  28. Main,
  29. Menu,
  30. MenuItem,
  31. Button,
  32. Form,
  33. FormItem,
  34. Input,
  35. Row,
  36. Col,
  37. Carousel,
  38. CarouselItem,
  39. Popover
  40. ].forEach((component) => Vue.component(component.name, component))
  41. }
  42. }
  43. Vue.use(Element, { locale })
  1. 在 nuxt.config.js 文件中,配置 plugins 选项。
  1. plugins: ["@/plugins/element-ui"],
  1. 如果在 create-nuxt-app 中默认选了 Element-UI 的,还需要将 Element-UI 的全局样式去掉,即在 nuxt.config.js 中:

    1. // css: ['element-ui/lib/theme-chalk/index.css'],
    2. // 改为
    3. css: [],
  2. 在 nuxt.config.js 文件中,在选项 build 中配置 babel 选项:

    1. build: {
    2. babel: {
    3. plugins: [
    4. [
    5. 'component',
    6. {
    7. libraryName: 'element-ui',
    8. styleLibraryName: 'theme-chalk'
    9. }
    10. ]
    11. ]
    12. }
    13. }

    到此,Element-UI 按需引入配置完成。

vue-in8n 多语言

  1. export default function ({ isHMR, app, store, route, params, error, redirect }) {
  2. const defaultLocale = app.i18n.fallbackLocale
  3. // If middleware is called from hot module replacement, ignore it
  4. if (isHMR) { return }
  5. // Get locale from params
  6. const locale = params.lang || defaultLocale
  7. if (!store.state.locales.includes(locale)) {
  8. return error({ message: 'This page could not be found.', statusCode: 404 })
  9. }
  10. // Set locale
  11. store.commit('SET_LANG', locale)
  12. app.i18n.locale = store.state.locale
  13. // If route is /<defaultLocale>/... -> redirect to /...
  14. if (locale === defaultLocale && route.fullPath.indexOf('/' + defaultLocale) === 0) {
  15. const toReplace = '^/' + defaultLocale + (route.fullPath.indexOf('/' + defaultLocale + '/') === 0 ? '/' : '')
  16. const re = new RegExp(toReplace)
  17. return redirect(
  18. route.fullPath.replace(re, '/')
  19. )
  20. }
  21. }
  1. import Vue from 'vue'
  2. import VueI18n from 'vue-i18n'
  3. Vue.use(VueI18n)
  4. export default ({ app, store }) => {
  5. // Set i18n instance on app
  6. // This way we can use it in middleware and pages asyncData/fetch
  7. app.i18n = new VueI18n({
  8. locale: store.state.locale,
  9. fallbackLocale: 'zh-CN',
  10. messages: {
  11. 'en-US': require('@/locales/en-US.json'),
  12. 'zh-CN': require('@/locales/zh-CN.json')
  13. }
  14. })
  15. app.i18n.path = (link) => {
  16. if (app.i18n.locale === app.i18n.fallbackLocale) {
  17. return `/${link}`
  18. }
  19. return `/${app.i18n.locale}/${link}`
  20. }
  21. }
  1. export const state = () => ({
  2. locales: ['en-US', 'zh-CN'],
  3. locale: 'zh-CN'
  4. })
  5. export const mutations = {
  6. SET_LANG(state, locale) {
  7. if (state.locales.includes(locale)) {
  8. state.locale = locale
  9. }
  10. }
  11. }

locales下创建翻译文件
image.png

  1. {
  2. "links": {
  3. "home": "Home",
  4. "about": "About",
  5. "english": "English version",
  6. "french": "French version"
  7. },
  8. "home": {
  9. "title": "Welcome",
  10. "introduction": "This is an introduction in English."
  11. },
  12. "about": {
  13. "title": "About",
  14. "introduction": "This page is made to give you more informations."
  15. }
  16. }
  1. export default {
  2. router: {
  3. middleware: ['i18n']
  4. },
  5. plugins: ['~/plugins/i18n.js'],
  6. generate: {
  7. routes: ['/', '/about', '/zh-CN', '/zh-CN/about'],
  8. fallback: true
  9. }
  10. }

修改 dev 端口

修改 package.json文件的scripts节点下的”dev”,在nuxt 后面加上 —port 9001,

  1. "scripts": {
  2. "dev": "nuxt --port 9001",
  3. "build": "nuxt build",
  4. "start": "nuxt start --port 9001",
  5. "generate": "nuxt generate"
  6. },

或者直接在package.json里面去加一段(这种方式还可以通过ip访问)

  1. "config": {
  2. "nuxt": {
  3. "host": "0.0.0.0",
  4. "port": "3333" //你就写与冲突的端口号不同的就行
  5. }
  6. }