搞懂vite

vite官网

vite视频讲解

💡
极速的服务启动
使用原生 ESM 文件,无需打包!

⚡️
轻量快速的热重载
无论应用程序大小如何,都始终极快的模块热替换(HMR)

🛠️
丰富的功能
对 TypeScript、JSX、CSS 等支持开箱即用。

📦
优化的构建
可选 “多页应用” 或 “库” 模式的预配置 Rollup 构建

🔩
通用的插件
在开发和构建之间共享 Rollup-superset 插件接口。

🔑
完全类型化的API
灵活的 API 和完整的 TypeScript 类型。

Vite(法语意为 “快速的”,发音 /vit/,发音同 “veet”)是一种新型前端构建工具,能够显著提升前端开发体验。它主要由两部分组成:
一个开发服务器,它基于 原生 ES 模块 提供了 丰富的内建功能,如速度快到惊人的 模块热更新(HMR)。
一套构建指令,它使用 Rollup 打包你的代码,并且它是预配置的,可输出用于生产环境的高度优化过的静态资源。
Vite 是一种具有明确建议的工具,具备合理的默认设置。您可以在 功能指南 中了解 Vite 的各种可能性。通过 插件,Vite 支持与其他框架或工具的集成。如有需要,您可以通过 配置部分 自定义适应你的项目。
Vite 还提供了强大的扩展性,可通过其 插件 API 和 JavaScript API 进行扩展,并提供完整的类型支持。

在开发阶段,Vite 将 esnext 作为转换目标,因为我们假设使用的是现代浏览器,它支持所有最新的 JavaScript 和 CSS 特性。这样可以防止语法降级,让 Vite 尽可能地接近原始源代码。

对于生产构建,默认情况下 Vite 的目标浏览器支持 原生 ES 模块、原生 ESM 动态导入 和 import.meta。旧版浏览器可以通过官方的 @vitejs/plugin-legacy。查看 构建生产环境 了解更多细节。

Vite是一个由原生ES module驱动的web开发构建工具,在开发环境下基于浏览器原生Es import开发,在生产环境下基于Rollup打包。

vite的特点有:

  • 闪电般的冷启动速度
  • 即使热更新
  • 真正的按需编译

要求:

vite 要求项目完全由esmodule模块组成
common.js模块不能在vite上使用
打包上依旧还是rollup等传统打包工具

vite的底层实现:

  1. 已知目录结构在这里插入图片描述
  2. App.vue内容
<template>
  <div>
    <h1>大家好,我是阿亮</h1>
    <h2>
      <span>count is {{ count }}</span>
      <button @click="count++">+1</button>
      <button @click="add">add+1</button>
    </h2>
  </div>
</template>

<script>
import { ref } from "vue";
export default {
  setup() {
    const count = ref(6);
    function add() {
      count.value++;
    }
    return { add, count };
  },
};
</script>
  1. index.css
h1 {color: red;}
  1. main.js
import { str } from './moduleA.js'
console.log('vite ...', str);
import { createApp, h } from 'vue';
import App from './App.vue'
import './index.css'
const App1 = {
    render() {
        // <div><div>hello vite</div></div>
        return h('div', null, [
            h('div', null, String('hello vite'))
        ])
    }
}
createApp(App).mount('#app')
  1. moduleA.js
export const str = 'zanlan 321'
  1. index.html
<h1>hello vite</h1>
<div id="app"></div>
<script src="./src/main.js" type="module"></script>
  1. index.js

sfc (single-file-components)

const Koa = require('Koa')

const fs = require('fs')
const path = require('path')
const app = new Koa()
const compilerSfc = require('@vue/compiler-sfc')
const compilerDom = require('@vue/compiler-dom')

app.use(async (ctx) => {
    const { url, query } = ctx.request
    console.log('url ------------' + url);
    if (url === '/') {
        ctx.type = 'text/html'
        let content = fs.readFileSync('./index.html', 'utf-8')
        content = content.replace('<script', `
            <script>
                window.process = {env:{NODE_ENV:'dev'}}
            </script>
        <script`)
        ctx.body = content
    } else if (url.endsWith('.js')) {
        //  /src/main.js => 代码文件所在位置/src/main.js
        const p = path.resolve(__dirname, url.slice(1))
        const content = fs.readFileSync(p, 'utf-8')
        ctx.type = 'application/javascript'
        ctx.body = rewriteImport(content)
    } else if (url.startsWith('/@modules')) {
        // 第三方库的支持
        // /@modules/vue => node_modules
        // /@modules/vue => 代码的位置/node_modules/vue/ 的es模块入口
        const prefix = path.resolve(
            __dirname,
            "node_modules",
            url.replace("/@modules/", "")
        )
        // 读取package.json的module属性
        const module = require(prefix + '/package.json').module
        const p = path.resolve(prefix, module)
        const ret = fs.readFileSync(p, 'utf-8')
        ctx.type = 'application/javascript'
        ctx.body = rewriteImport(ret)
    } else if (url.indexOf('.vue') > -1) {
        // /*.vue?type = template
        const p = path.resolve(__dirname, url.split('?')[0].slice(1))
        const { descriptor } = compilerSfc.parse(fs.readFileSync(p, 'utf-8'))
        if (!query.type) {
            // 第一步vue文件 => template script (compiler-sfc)
            // descriptor => js + template生成render部分
            ctx.type = "application/javascript"
            // 借用vue自导的compile框架,解析单文件组件,其实相当于vue-loader做的事情
            ctx.body = `
            ${rewriteImport(
                descriptor.script.content.replace("export default", "const __script = ")
            )}
            import { render as __render } from "${url}?type=template"
            __script.render = __render
            export default __script
            `
        } else {
            // 第二步 template模板 => render函数(compiler-dom)
            const template = descriptor.template
            const render = compilerDom.compile(template.content, { mode: 'module' })
            ctx.type = "application/javascript"
            console.log('render', render);
            ctx.body = rewriteImport(render.code)
        }
    } else if (url.endsWith('.css')) {
        console.log('9999999999999999999999999');
        const p = path.resolve(__dirname, url.slice(1))
        const file = fs.readFileSync(p, 'utf-8')
        // css转换为js代码
        // 利用js添加一个style标签
        const content = `
            const css = "${file.replace(/\n/g, "")}"
            let link = document.createElement('style')
            link.setAttribute('type','text/css')
            document.head.appendChild(link)
            link.innerHTML = css
            export default css
        `
        ctx.type = 'application/javascript'
        ctx.body = content
    }



    // 第三方库的支持
    // vue => node_modules/***
    // 改写函数
    // 需要改写 欺骗一下浏览器 'vue' => '/@modules/vue' => 别名
    // from 'xxx'
    function rewriteImport(content) {
        return content.replace(/ from ['|"]([^'"]+)['|""]/g, (...args) => {
            if (args[1][0] !== '.' && args[1][1] !== '/') {
                return ` from '/@modules/${args[1]}'`
            } else {
                return args[0]
            }
        })
    }
    /**
    rewriteImport('import { createApp, h } from \'vue\'')
	"import { createApp, h } from '/@modules/vue'"
*/

})

app.listen(3000, () => {
    console.log('vite start at 3000');
})
  1. pakage.json
{
  "name": "vite",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "koa": "^2.13.4",
    "vue": "^3.2.36"
  }
}
  1. 执行node index.js
  2. 在页面上输入 localhost:3000,展示页面如下: 在这里插入图片描述
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值