vite工程化实践

661 阅读6分钟

vite 一种新型的前端构建工具 StackBlitz 在线试用

搭建一个Vite项目

node版本>=12.0.0

$ npm init vite@latest

$ yarn create vite

//附加的命令行选项直接指定项目名称和想要使用的模板
//要构建一个 Vite + Vue 项目

# npm 6.x
npm init vite@latest my-vue-app --template vue

# npm 7+, 需要额外的双横线:
npm init vite@latest my-vue-app -- --template vue

# yarn
yarn create vite my-vue-app --template vue

代码组织形式分析

关键变化是 index.html 中的入口文件导入方式

<script type="module" src="/src/main.js"></script>

这样main.js 中就可以使用 ES6 Module 方式组织代码

import { createApp } from 'vue'
import App from './App.vue'
import './index.css'

浏览器会自动加载这些导入,vite会启动一个本地服务器处理不同这些加载请求,对于相同地址的导入,要根据后缀名处理文件内容并返回,对于裸模块导入要修改它的路径为相对地址并再次请求处理。

image.png

再根据模块package.json 中的入口文件选项获取要加载的文件。

"module": "dist/runtime-core.esm-bundler.js",

对于开发者而言,整体没有大的变化

资源加载方式

CSS文件导入

vite中可以直接导入 .css 文件,样式将影响导入的页面,最终会被打包到 style.css

在我们程序中,除了全局样式大部分样式都是以<style>形式存在于SFC中

CSS Module

1. SFC 中使用 CSS Module

<style module> 范例:使用 CSS Module 修改 Dashboard.vue 中 p 样式

<p :class="$style['click-count']" @click="add">
    {{state.count}}
</p>

<style module>
.click-count{
  background-color: salmon;
}
</style>

2. JS中导入 CSS Module

将css文件命名为 *.module.css 即可

import style from './dashboard.module.css'

export default{
    computed:{
        $style(){
            return style
        }
    }
}

CSS 预处理器

安装对应的预处理器就可以直接在vite项目中使用

<style lang = "scss">
/* use scss */
</style>

//或者在js中导入
import './style.scss'

PostCSS

vite 自动对 *.vue文件和导入的 .css 文件应用PostCSS配置,我们只需要安装必要的插件和添加 postcss.config.js文件即可。

npm i postcss autoprefixer -D
//@8.14

module.exports = {
    plugins:[
        require('autoprefixer')
    ]
}

资源URL处理

引用静态资源

我们可以在 *.vue 文件的template、style和纯 .css 文件中以相对和绝对路径方式引用静态资源。

<!-- 相对路径 -->
<img src = "./assets/logo.png">
<!-- 绝对路径 -->
<img src = "/src/assets/logo.png">

<style>
#app {
    background-image:url('./assets/logo.png');
}
</style>

public 目录

public 目录下可以存放未在源码中引用的资源,它们会被留下且文件名不会有哈希处理。 这些文件会被原封不动拷贝到发布目录的根目录下。

<img src = "/logo.png">

注意:引用放置在public目录下的文件需要使用绝对路径,例如public/icon.png 应该使用/icon.png 引用

代码规范和格式化 eslint+prettier

借助eslint规范项目代码,通过prettier做代码格式化。

注意:eslint 和 prettier设置要一致

  1. 安装依赖,package.json npm i @vue/eslint-config-prettier babel-eslint eslint eslint-plugin-prettier eslint-plugin-vue prettier

Must use import to load ES Module: F:\vue3_coresreset\vue3-study\demo\vite-vue\node_modules@eslint\eslintrc\universal.js image.png

{
  "scripts": {
    "lint": "eslint \"src/**/*.{js,vue}\""
  },
  "devDependencies": {
    "@vue/eslint-config-prettier": "^6.0.0",
    "babel-eslint": "^10.1.0",
    "eslint": "^6.7.2",
    "eslint-plugin-prettier": "^3.1.3",
    "eslint-plugin-vue": "^7.0.0-0",
    "prettier": "^1.19.1"
  }
}
  1. 然后配置lint规则,.eslintrc.js
module.exports = {
    root: true,
    env: {
        node: true,
    },
    extends: ["plugin:vue/vue3-essential", "eslint:recommended", "@vue/prettier"],
    parserOptions: {
        parser: "babel-eslint",
    },
    rules: {
        "no-console": process.env.NODE_ENV === "production" ? "warn" : "off",
        "no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off",
        "prettier/prettier": [
            "warn",
            {
                // singleQuote: none, 单引号
                // semi: false, 分号
                // trailingComma: "es5", //对象或数组最后一项是否加逗号
            },
        ],
    },
};
  1. 如果有必要还可以配置prettier.config.js 修改prettier的默认格式化规则
module.exports = {
    printWidth: 80, // 每行代码长度(默认80)
    tabWidth: 4, // 每个tab相当于多少个空格(默认2)
    useTabs: false, // 是否使用tab进行缩进(默认false)
    singleQuote: false, // 使用单引号(默认false)
    semi: true, // 声明结尾使用分号(默认true)
    // trailingComma: 'es5', // 多行使用拖尾逗号(默认none)
    bracketSpacing: true, // 对象字面量的大括号间使用空格(默认true)
    jsxBracketSameLine: false, // 多行JSX中的>放置在最后一行的结尾,而不是另起一行(默认false)
    arrowParens: "avoid" // 只有一个参数的箭头函数的参数是否带圆括号(默认avoid)
};

TypeScript 整合

vite 可直接导入.ts文件,在SFC中通过<script lang="ts"> 使用

ts版本指定,package.json

"devDependencies": {
    "typescript": "^3.9.7"
  }

项目配置

项目根目录创建vite.config.js,可以对vite项目进行深度配置

定义别名

alias: {
    // v1.x
    "/comps/": path.resolve(__dirname, "src/components")
    
    // v2.x 去除后一个斜线
    "/comps": path.resolve(__dirname, "src/components")
},

代理

配置服务器代理,vite.config.js

export default {
    proxy: {
        '/api': {
            target: 'http://jsonplaceholder.typicode.com',
            changeOrigin: true,
            rewrite: path => path.replace(/^\/api/, '')
        }
    }
}

使用

fetch("/api/users") 
.then(response => response.json()) 
.then(json => console.log(json));

数据mock

npm i mockjs -S 
npm i vite-plugin-mock cross-env -D    //1.0.6版本


npm i vite-plugin-mock -D
  • 引入插件
plugins: [
    createMockServer({
        // close support .ts file
        supportTs: false,
    })
]
  • 设置环境变量,package.json
"dev": "cross-env NODE_ENV=development vite"
  • 创建 mock文件,mock/test.js
export default [
    {
        url: "/api/users",
        method: "get",
        response: req => {
            return {
                code: 0,
                data: [
                    {
                        name: "tom",
                    },
                    {
                        name: "jerry",
                    },
                ],
            };
        },
    },
    {
        url: "/api/post",
        method: "post",
        timeout: 2000,
        response: {
            code: 0,
            data: {
                name: "vben",
            },
        },
    },
];

模式和环境变量

使用模式做多环境配置,vite serve时模式默认是developmentvite build时是production

  • 创建配置文件 .env.development VITE_TOKEN=this is token
  • 代码中读取 import.meta.env.VITE_TOKEN

打包和部署

执行 npm run build 打包

手动上传dist中的内容到服务器,再配置好nginx当然可以,但是这一过程最好自动化处理,避免前面这些繁琐的操作。我们这里利用github actions实现ci/cd过程。

Github Actions让我们可以在Github仓库中直接创建自定义的软件开发生命周期工作流程。

1. 配置workflow 下面的配置可以在我们push代码时自动打包我们应用并部署到阿里云服务器上,在项目根目录下创建.github/workflows/publish.yml

name: 打包应用并上传阿里云

on:
  push:
    branches:
      - "main"

jobs:
  build:
    # runs-on 指定job任务运行所需要的虚拟机环境(必填字段)
    runs-on: ubuntu-latest
    steps:
      # 获取源码
      - name: 迁出代码
        # 使用action库  actions/checkout获取源码
        uses: actions/checkout@master
      # 安装Node10
      
      - name: 安装node.js
        # 使用action库  actions/setup-node安装node
        uses: actions/setup-node@v1
        with:
          node-version: 14.0.0

      # 安装依赖
      - name: 安装依赖
        run: npm install

      # 打包
      - name: 打包
        run: npm run build

      # 上传阿里云
      - name: 发布到阿里云
        uses: easingthemes/ssh-deploy@v2.1.1
        env:
          # 私钥 -- 服务器上的私钥
          SSH_PRIVATE_KEY: ${{ secrets.ALIYUN_SERVER_ACCESS_TOKEN }}
          # scp参数
          ARGS: "-avzr --delete"
          # 源目录
          SOURCE: "dist"
          # 服务器ip:换成你的服务器IP
          REMOTE_HOST: "47.104.154.73"
          # 用户
          REMOTE_USER: "root"
          # 目标地址
          TARGET: "/home/vue-in-action"

2. 在gitHub当前项目下设置私钥选项

  • 配置secret

  1. 到服务器中,运行
ssh-keygen -m PEM -t rsa -b 4096

// 非PEM格式,可能会报错Load key “/home/runner/.ssh/deploy_key”: invalid format
  1. 将公钥写入.ssh/authorized_keys
cd ~/.ssh 
cat id_rsa.pub >> ~/.ssh/authorized_keys

vim ~/.ssh/authorized_keys

//vim查看,此时authorized_keys会多出密钥
  1. 复制私钥:将内容复制下来,来到GitHub仓库,进入 Secrets 配置
cat id_rsa
  • 复制服务器的私钥

image.png

  • 复制并填写到 github-secretes

image.png

3. 在阿里云服务器上配置nginx 安装nginx

  • 登录服务器
ssh root@47.104.154.73
  • 配置 nginx
//到nginx 安装目录
 cd /etc/nginx
 
 //添加自己的配置
 server { 
     listen 8080; 
     server_name 47.98.252.43; 
     root /home/vue-in-action/dist/;
     location / { 
         index index.html index.htm;
     }
 }
 
  • 重启 nginx nginx -s reload

  • push 代码 - 触发 workflow

image.png

大功告成 - 访问 http://47.104.154.73:8080 试试效果吧

待...

  • 测试环境 利用jest@vue/test-utils测试组件 npm install jest vue-jest babel-jest @babel/core @babel/preset-env @vue/test-utils
  • 安装依赖
  • 配置 babel.config.js
  • 配置 jest.config.js