laclys / Front-End_practice

Daily practice
5 stars 0 forks source link

vite note #156

Open laclys opened 3 years ago

laclys commented 3 years ago

构建工具的高阶封装,最核心的是rollup 和Vue3一起发布的。2.0之后完全独立的框架

vitejs.dev

目标

类似产品

(官网对比)

Vite做的最好的一个

和传统构建工具对比

vite:

vs webpack vs rollup

看webpack的官网 documentation 非常非常复杂。功能非常非常多,也非常强大。它希望把它能考虑加载的东西全部加载进去。同时它也希望它的核心功能帮助其他功能进行实现。比如我们可以基于webpack 实现一个webpack-dev-server。其实也是围绕webpack核心功能进行构建的。 它有各种各种构建的方式

rollup更加单一专一的工具。rollup诞生的目的就是build ES Module。同时它只专注于build js而不考虑平台。

对于webpack 我们编译出来代码会有很多webpack本身的工具函数。帮助我们加载模块。rollup不会有什么它专有的函数在里面。它会遵循esm的标准。它build出来的代码就符合common.js的标准或者是像umd的标准。没有自己的工具在里面,比较纯粹。只是符合这个规范。rollup初衷不是前端项目,而是工具类库。

vite:目标是工程、项目开发。不像webpack和rollup他们是工具,更加focus或者说执行的是”构建“。vite更加上层。High Level,初衷就是更好的体验,一开始设计就是为了去解决项目开发构建。学习成本比webpack、rollup低很多。

总结:webpack更全面,rollup更专一,vite为项目而生而不是为构建而生。

Vite: 自身插件系统 生态兼容rollup

1.0 vue3

2.0 跨框架

React

FastRefresh: (官方插件)相比react-hot-loader。解决了很多rhl无法解决的问题;速度更快;以及支持局部更新

laclys commented 3 years ago

vite css

// https://vitejs.dev/config/ export default defineConfig({ plugins: [reactRefresh()], server: { host: '0.0.0.0', }, / !!!!!! / resolve: { alias: { "@/styles": "/src/styles", } } })

*** src前记得加`/`

```typescript
import '@/styles/....'
@import url("@/styles/xxx.css");
laclys commented 3 years ago

ts

vite只编译,不校验(如果需要校验:tsc --noEmit tsconfig.json增加”types”:["vite/client"] 来运用vite内部支持的内部变量

// eg:
import.meta.env
  • Asset imports
  • env
  • HMR API
laclys commented 3 years ago

静态资源

import Worker from './workder?worker // ./workder是自定义的js function
const worker = new Worker()
worker.onmessage = function(e) {
// content
}
laclys commented 3 years ago

vite 环境变量

import.meta.env

内置:MODEBASE_URLPRODDEVSSR

.env.development.local -> 本地环境

也可以自定义.env.testnet ---》 vite --mode testnet

在vite-env.d.ts中声明自定义环境变量可以有代码提示


interface ImportMetaEnv {
....
}
``
laclys commented 3 years ago

Vite HMR

Vite的HMR和webpack的不一样。它是完全基于游览器原生ESM进行模块管理。相比webpack的模块管理更加轻量且易于使用。

_webpack自己实现模块管理成本非常大(webpack编译出来的代码:__webpack_require__)_

而且vite的HMR也相对更集中于模块本身,不会有webpack类似的大面积影响

vite命令行 生成的项目默认开启热更新

HMR API

Vite自己实现的 没有用rollup(rollup本身也不支持)

简单实现

创建一个原生js的vite项目,它本身是不支持HMR的

npm init @vitejs/app

✔ Project name: … hmr-test
✔ Select a framework: › vanilla
✔ Select a variant: › vanilla
截屏2021-09-19 下午4 07 47
// main.js
import './style.css'

document.querySelector('#app').innerHTML = `
  <h1>Hello Vite!</h1>
  <a href="https://vitejs.dev/guide/features.html" target="_blank">Documentation</a>
`

在这里改变h1上面的内容 需要手动刷新才行。这里我们把它改造成HMR

import './style.css'

export function render() {
  document.querySelector('#app').innerHTML = `
    <h1>Hello Vite!123</h1>
    <a href="https://vitejs.dev/guide/features.html" target="_blank">Documentation</a>
  `
}

render()

// production bundle里面没有 hot代码
if (import.meta.hot) {
  // 代表这个文件接收自己的热更新。我们一旦执行了`import.meta.hot.accept` 就代表这个文件会接收自己的热更新
  // import 对的是一个模块的概念 我接受了我这个模块的更新
  import.meta.hot.accept((newModule) => {
    newModule.render()
  })
}

这样就初步实现了热更新 不过是非常针对性的功能 注意 这里 必须写成newModule.render(),为什么不能直接render()呢。因为JS的闭包。!!!

实现: websocket 上连接 修改内容 我们就会看到 updates 告诉浏览器有文件更新 截屏2021-09-19 下午4 20 24

main.js第二次请求 截屏2021-09-19 下午4 21 48

laclys commented 3 years ago

glob import

批量导入

const globModules = import.meta.glob('./glob/*')

laclys commented 3 years ago

预编译

  1. CommonJs -> ESM 2. bundle files together
laclys commented 2 years ago

nodejs中集成 vite

最基础的

const express = require('express')

const app = express()

const { createServer: createViteServer } = require('vite')

createViteServer({
  server: {
    middlewareMode: 'html' // 启动vite dev server 和vite启动没区别
  }
}).then((vite) => {
  app.use(vite.middlewares)

  app.listen(4399)
})

SSR

开发模式


const express = require('express')

const app = express()

const { createServer: createViteServer } = require('vite')

createViteServer({ server: { middlewareMode: 'ssr' // 改变了这里 } }).then((vite) => { app.use(vite.middlewares)

app.listen(4399) })

run一下
![截屏2021-09-23 上午12 10 58](https://user-images.githubusercontent.com/22010181/134381417-7e160fc0-f847-40d2-bae0-8e0837f77544.png)

> vite在`ssr`mode下对于请求的管理 ,会转交给我们自己的`server`。而不是`vite dev server`去处理。需要我们自己完成

src添加 服务端入口文件
```javascript
// server-entry.jsx
import React from 'react' 
import ReactDOMServer from 'react-dom/server'
import App from './App'

export function render(url, context) {
  return ReactDOMServer.renderToString(<App />)
}
模板添加` <!-- App_HTML -->` 标识 用于替换
```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/src/favicon.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vite App</title>
  </head>
  <body>
    <div id="root">
      <!-- App_HTML -->
    </div>
    <script type="module" src="/src/main.tsx"></script>
  </body>
</html>

Server!

const express = require('express')
const fs = require('fs')

const app = express()

const { createServer: createViteServer } = require('vite')

createViteServer({
  server: {
    middlewareMode: 'ssr',
  },
}).then((vite) => {
  app.use(vite.middlewares)

  app.get('*', async (req, res) => {

    let template = fs.readFileSync('index.html', 'utf-8')

    template = await vite.transformIndexHtml(req.url, template)

    const { render } = await vite.ssrLoadModule('/src/server-entry.jsx') // 这里要注意 纠结排查了很久 有参数(项目服务端渲染入口文件)&& 异步!!

    const html = render(req.url)

    const responseHtml = template.replace(`<!-- App_HTML -->`, html)

    res.set('content-type', 'text/html')
    res.send(responseHtml)
  })

  app.listen(4399)
})

万事俱备只欠东风

node server.js

我们可以看到 SSR生效了 截屏2021-09-23 下午11 15 45

laclys commented 2 years ago

Node集成build的vite SSR App

https://github.com/laclys/Front-End_practice/tree/master/vite/vite-react