SlideShare a Scribd company logo
New Ways to Vue
ANTHONY FU
新技術和工具如何影響我們編寫Vue 專案的方式
Oct. 17th, 2021
Anthony Fu
antfu
antfu7
antfu.me
Vue & Vite 核心團隊成員

Slidev, VueUse, Vitesse, Type Challenges 等項目作者

狂熱的開源愛好者,目前任職於NuxtLabs。
在GitHub 上贊助我
New Ways to Vue
Vue 2 中的編寫方式
"腳手架程式碼"
可擴展性
TypeScript 支援
<script>
import Vue from 'vue'
import Foo from './components/Foo.vue'
import { mixinBar } from './mixins/bar'
export default Vue.extend({
components: {
Foo,
// ...
},
mixins: {
mixinBar,
// ...
},
props: {
value: {
type: String
},
// ...
},
data() {
return {
// ...
}
存在的問題
組合式API
物件式 API 組合式 API
data() {
methods: {
created() {
destroyed() {
export default {
return {
dark: false,
media: matchMedia('(prefers-color-scheme: dark)')
}
},
toggleDark() { this.dark = !this.dark },
update() { this.dark = this.media.matches }
},
this.media.addEventListener('change', this.update)
this.update()
},
this.media.removeEventListener('change', this.update)
}
}
setup() {
onUnmounted(() => {
import { ref, onUnmounted } from 'vue'
export default {
const media = matchMedia('(prefers-color-scheme: dark)
const dark = ref(media.matches)
const update = () => dark.value = media.matches
const toggleDark = () => dark.value = !dark.value
media.addEventListener('change', update)
media.removeEventListener('change', update)
})
return { dark, toggleDark }
}
}
可組合性
<!-- DarkToggle.vue -->
<script>
import { useDark } from './useDark'
export default {
setup() {
return {
...useDark()
}
}
}
</script>
// useDark.js
import { ref, onUnmounted } from 'vue'
export function useDark() {
const media = matchMedia('(prefers-color-scheme: dark)')
const dark = ref(media.matches)
const update = () => dark.value = media.matches
const toggleDark = () => dark.value = !dark.value
media.addEventListener('change', update)
onUnmounted(() => {
media.removeEventListener('change', update)
})
return { dark, toggleDark }
}
<script setup> 語法
<script> <script setup>
頂層變數和函式宣告
變數和組件將直接可以在模板中使用
Vue 3.2 中已穩定
` `
` ` ` `
import MyButton from './MyButton.vue'
const counter = ref(0)
const doubled = computed(() => counter.value * 2)
function inc() {
counter.value += 1
}
<script>
import { ref, computed } from 'vue'
export default {
components: {
MyButton,
},
setup() {
return { counter, doubled, inc }
}
}
</script>
<script setup>
import { ref, computed } from 'vue'
import MyButton from './MyButton.vue'
const counter = ref(0)
const doubled = computed(() => counter.value * 2)
function inc() {
counter.value += 1
}
</script>
<style> 中的 v-bind() 語法
` ` ` `
WITHOUT WITH V-BIND()
<button :style="{ color: buttonColor }">
data() {
return {
buttonColor: 'green'
}
}
<template>
My Button
</button>
</template>
<script>
export default {
}
</script>
<style>
button {
border-radius: 4px;
}
</style>
const buttonColor = ref('green')
color: v-bind(buttonColor);
<template>
<button>My Button</button>
</template>
<script setup>
</script>
<style>
button {
border-radius: 4px;
}
</style>
全新的默認開發工具Vite
+
Vite 是什麼?
打包器Bundlers
主要為生產環境構建設計
需要先打包整個專案才能讓開發伺
服器啟動
需要複雜的配置
模塊熱更新(HMR)隨著項目變大
而顯著變慢
Webpack Rollup
構建優先 BUILD FIRST
開發用伺服器Dev Server
專為前端開發設計
不打包+ 使用原生ESM
按需編譯
伺服器瞬間準備完成
瞬間的熱更新HMR
…更多新功能
Snowpack Vite
開發優先 DEV FIRST
Vue 3 和Vite 給我們帶來了什麼?
更快的速度和更好的開發體驗
New Ways to View
使用組件
使用 import 導入,並取一個名字
註冊組件
在模板中使用它
冗余
組件的名字至少被重複了四次
<template>
<my-container>
<my-button />
<my-input />
</my-container>
</template>
<script>
import MyContainer from '../components/MyContainer.vue'
import MyButton from '../components/MyButton.vue'
import MyInput from '../components/MyInput.vue'
export default {
components: {
MyContainer,
MyButton,
MyInput,
}
}
</script>
要使用一個組件
` `
問題
使用組件
導入可以直接在模板中使用
不再需要註冊組件
組件的名字還是被重複了三次
<template>
<my-container>
<my-button />
<my-input />
</my-container>
</template>
<script setup>
import MyContainer from '../components/MyContainer.vue'
import MyButton from '../components/MyButton.vue'
import MyInput from '../components/MyInput.vue'
</script>
使用 <SCRIPT SETUP> 語法
` `
但是…
組件自動導入
使用
收工!
編譯期組件解析
在 src/components 資料夾下的組件將被自動導入
Code-splitting
不再需要手動註冊組件
跳過了運行時組件解析
antfu/vite-plugin-components
vite-plugin-components
<template>
<my-container>
<my-button />
<my-input />
</my-container>
</template>
怎麼做到的?
` `
不同於全局組件註冊
編譯期解析
將會被 @vue/sfc-compiler 編譯成(可以通過https://sfc.vuejs.org 查看)
<template>
<my-container>
<my-button />
<my-input />
</my-container>
</template>
` `
const _component_my_button = _resolveComponent("my-button")
const _component_my_input = _resolveComponent("my-input")
const _component_my_container = _resolveComponent("my-container")
import { resolveComponent as _resolveComponent } from "vue"
function render(_ctx, _cache) {
return (_openBlock(), _createBlock(_component_my_container, null, {
default: _withCtx(() => [
_createVNode(_component_my_button),
_createVNode(_component_my_input)
]), _: 1 /* STABLE */
}))
}
編寫一個Vite 插件
使用 enforce: post 確保在Vue 編譯後執行
使用 transform 鉤子進行程式碼變換
過濾掉不是Vue 的檔案
將 _resolveComponent 替換成直接導入的組件
return code.replace(
/_resolveComponent("(.+?)"/g,
(_, name) => {
const component = findComponent(name)
// 注入導入程式碼 (略)
return component.path
})
// vite.config.ts
export default {
plugins: [{
name: 'my-plugin',
enforce: 'post',
transform(code, id) {
if (!id.endsWith('.vue'))
return
}
}]
}
` `
` `
` `
請參照Vite Plugin API 官方文件
最終結果
替換後產物
const _component_my_button = _resolveComponent("my-button")
const _component_my_input = _resolveComponent("my-input")
const _component_my_container = _resolveComponent("my-container")
import { resolveComponent as _resolveComponent } from "vue"
function render(_ctx, _cache) {
return () => /* ... */
}
import _component_my_button from "../components/MyButton.vue"
import _component_my_input from "../components/MyInput.vue"
import _component_my_container from "../components/MyContainer.vue"
import { resolveComponent as _resolveComponent } from "vue"
function render(_ctx, _cache) {
return () => /* ... */
}
檢閱模組樹Inspect Module Graph
獲悉每次變換的中間狀態
antfu/vite-plugin-inspect
0:00
API 自動導入
類似的,我們也可以做到API 自動導入
antfu/unplugin-auto-import
<script setup>
import { ref, computed, watch } from 'vue'
import { debouncedWatch } from '@vueuse/core'
const counter = ref(0)
const doubled = computed(() => counter.value * 2)
debouncedWatch(counter, () => {
console.log('counter changed')
})
</script>
<script setup>
const counter = ref(0)
const doubled = computed(() => counter.value * 2)
debouncedWatch(counter, () => {
console.log('counter changed')
})
</script>
使用圖標Icons
Icon Fonts
需要打包整圖標集
FOUC (無樣式的閃爍)
SVG
需要手動引入
無法根據上下文上色
圖標組件
依賴於圖標集的實現
需要手動註冊
受啟發於Vite 的“按需分配” 理念,我們可以讓圖標在編譯期按需分配
透過Iconify,我們可以讓100+ 圖標集的10,000+ 圖標使用相同的語法導入
插件將會按需將虛擬模組編譯成對應的圖標組件
antfu/vite-plugin-icons
以往的方式 更好的解決方案?
<script setup>
import MdiAlarm from '~icons/mdi/alarm'
import FaBeer from '~icons/fa/beer'
import TearsOfJoy from '~icons/twemoji/face-with-tears-of-joy'
</script>
<template>
<MdiAlarm />
<FaBeer style="color: orange"/>
<TearsOfJoy/>
</template>
import Icon from '~icons/[collection]/[id]'
圖標按需導入
按需引入,只有用到的圖標才會被被打包
可以使用幾乎任何圖標
可直接使用 class 和 style 修改樣式
SSR / SSG 友好
配合 vite-plugin-components ,獲得類似Icons Fonts 的體驗
` ` ` `
` `
<template>
<MdiAlarm />
<FaBeer style="color: orange"/>
<TearsOfJoy/>
</template>
Vite 生態系統
- 組件自動引入
- API 自動引入
- 按需分配的圖標方案
- 檢視Vite 內部狀態
- 檔案系統路由生成器
- Windi CSS (按需生成的Tailwind CSS)
- 為後端Node 應用提供Vite HMR
- 按需引入組件樣式
...以及更多
vite-plugin-components
vite-plugin-auto-import
vite-plugin-icons
vite-plugin-inspect
hannoeru/vite-plugin-pages
vite-plugin-windicss
axe-me/vite-plugin-node
anncwb/vite-plugin-style-import vitejs/awesome-vite
One more thing
把他們帶到你現有的專案中
今天就行!
Vite 的設計思想激發了很多新的工具和開發體驗
Introducing unplugin
通用化的插件API,可用於Webpack,Vite,Rollup 等等...
編寫一次但適用於:
Unplugin unjs/unplugin
VITE 插件 UNPLUGIN
export const VitePlugin = () => {
return {
name: 'my-first-unplugin',
transform (code) {
return code.replace(
/<template>/,
`<template><div>Injected</div>`
)
},
}
}
import { createUnplugin } from 'unplugin'
export const unplugin = createUnplugin(() => {
return {
name: 'my-first-unplugin',
transform (code) {
return code.replace(
/<template>/,
`<template><div>Injected</div>`
)
},
}
})
export const VitePlugin = unplugin.vite
export const RollupPlugin = unplugin.rollup
export const WebpackPlugin = unplugin.webpack
Vite 插件 Unplugins
unplugin-vue-components
unplugin-auto-import
For Vue / React / Svelte / Vanila / Any framework
unplugin-icons
Vue
React
Preact
Svelte
SolidJS
Web Components
Vanila
...
Vite
Nuxt
Next.js
Rollup
Vue CLI
Webpack
...
Carbon Icons
Material Design Icons
Unicons
Twemoji
Tabler
BoxIcons
EOS Icons
...
vite-plugin-components
` ` ` `
vite-plugin-auto-import
` ` ` `
vite-plugin-icons
` ` ` `
那Vue 2 如何?
沒問題,替你想好了!
Vue 2
組合式API: @vue/composition-api
<script setup> 語法和Ref 語法糖: unplugin-vue2-script-setup
vite-plugin-vue2
nuxt-vite
unplugin-vue-components
unplugin-auto-import
unplugin-icons
POLYFILLS
` `
` ` ` `
VITE 支援
` `
` `
開發體驗
` `
` `
` `
打包帶走
今天就能獲得的開發體驗,不管你是用Vue 2, Vue 3, Vite, Nuxt, 還是Vue CLI 都可以!
<template>
<button>
<IconSun v-if="dark"/>
<IconMoon v-else/>
</button>
</template>
<script>
import IconSun from '@some-icon-set/sun'
import IconMoon from '@some-icon-set/moon'
export default {
components: {
IconSun,
IconMoon,
},
data() {
return {
dark: false,
media: matchMedia('(prefers-color-scheme: dark)')
}
},
<script setup>
const dark = useDark()
</script>
<template>
<button>
<IconSun v-if="dark"/>
<IconMoon v-else/>
</button>
</template>
起手專案模板
Vue 3 + Vite 專案模板
在Nuxt 2 上獲得Vitesse 開發體驗
Vitesse 瀏覽器插件版本
Spoiler: Nuxt 3 將會原生提供許多上面提到的功能!
預置了上面提到的所有插件和配置
antfu/vitesse
antfu/vitesse-nuxt
antfu/vitesse-webext
現在嘗試!
npx degit antfu/vitesse
謝謝!
簡報可以在antfu.me 下載

More Related Content

What's hot (20)

PPT
13090016_vectorcast.ppt
Karthika Keshav
 
PDF
Infrastructure as Code for Beginners
David Völkel
 
PPTX
GIT AND GITHUB (1).pptx
GDSCCVRGUPoweredbyGo
 
PDF
Understanding VMware Cloud on AWS
RightScale
 
PDF
ROAD map for Software test engineer.pdf
Pavithra227722
 
PDF
DevOps beyond the Tools
Johann-Peter Hartmann
 
PDF
Chaos Engineering 시작하기 - 윤석찬 (AWS 테크에반젤리스트) :: 한국 카오스엔지니어링 밋업
Channy Yun
 
PPTX
How to Get Started with Cypress
Applitools
 
PDF
Portlet Specification 3.0 Is Here!
Dev_Events
 
PDF
Branching Out: How To Automate Your Development Process
Perforce
 
PDF
Test Automation Strategy
Martin Ruddy
 
PPT
QACampus PPT (STLC)
QACampus Noida
 
PPS
JUnit Presentation
priya_trivedi
 
PDF
.NET 7 家族新成員: Microsoft Orleans v7
twMVC
 
DOC
Rahul_Auti_Sr. Test Engineer_Manual & Automation_Testing_6_Yrs - Copy
Rahul Auti
 
PPTX
Unit Testing in Java
Ahmed M. Gomaa
 
PDF
Effort Distribution on Waterfall and Agile
Ananda Pramanik
 
PDF
ATDD Using Robot Framework
Pekka Klärck
 
PPTX
Exploratory testing workshop
Anne-Marie Charrett
 
PPT
Web assembly overview by Mikhail Sorokovsky
Valeriia Maliarenko
 
13090016_vectorcast.ppt
Karthika Keshav
 
Infrastructure as Code for Beginners
David Völkel
 
GIT AND GITHUB (1).pptx
GDSCCVRGUPoweredbyGo
 
Understanding VMware Cloud on AWS
RightScale
 
ROAD map for Software test engineer.pdf
Pavithra227722
 
DevOps beyond the Tools
Johann-Peter Hartmann
 
Chaos Engineering 시작하기 - 윤석찬 (AWS 테크에반젤리스트) :: 한국 카오스엔지니어링 밋업
Channy Yun
 
How to Get Started with Cypress
Applitools
 
Portlet Specification 3.0 Is Here!
Dev_Events
 
Branching Out: How To Automate Your Development Process
Perforce
 
Test Automation Strategy
Martin Ruddy
 
QACampus PPT (STLC)
QACampus Noida
 
JUnit Presentation
priya_trivedi
 
.NET 7 家族新成員: Microsoft Orleans v7
twMVC
 
Rahul_Auti_Sr. Test Engineer_Manual & Automation_Testing_6_Yrs - Copy
Rahul Auti
 
Unit Testing in Java
Ahmed M. Gomaa
 
Effort Distribution on Waterfall and Agile
Ananda Pramanik
 
ATDD Using Robot Framework
Pekka Klärck
 
Exploratory testing workshop
Anne-Marie Charrett
 
Web assembly overview by Mikhail Sorokovsky
Valeriia Maliarenko
 

Similar to 2021laravelconftwslides12 (20)

PPTX
利用Signalr打造即時通訊@Tech day geek
Johnson Gau
 
PDF
怎樣在 Flutter app 中使用 Google Maps
Weizhong Yang
 
PDF
I os 01
信嘉 陳
 
PPTX
容器驅動開發 - .NET Conf 2017 @ 台中
Andrew Wu
 
PDF
Introduction to MVC of CodeIgniter 2.1.x
Bo-Yi Wu
 
PPTX
Visual studio 2012 與 asp.net 4.5 (新功能與開發介紹) 第一天
Gelis Wu
 
PDF
[GDG Kaohsiung DevFest 2023] 以 Compose 及 Kotlin Multiplatform 打造多平台應用程式
Shengyou Fan
 
PDF
ASP.NET Core 2.1設計新思維與新發展
江華 奚
 
PPTX
猫粮快报
tbmallf2e
 
PDF
I os 02
信嘉 陳
 
PDF
Windows Mobile 多媒體應用程式開發
Chui-Wen Chiu
 
PPT
Osgi Intro
Ching Yi Chan
 
PDF
Responsive Web UI Design
jay li
 
PPTX
常用开发工具介绍
haozes
 
PDF
[JCConf 2023] 從 Kotlin Multiplatform 到 Compose Multiplatform:在多平台間輕鬆共用業務邏輯與 U...
Shengyou Fan
 
PDF
Uliweb cheat sheet_0.1
modou li
 
PDF
Spring 2.x 中文
Guo Albert
 
PPTX
Flutter Forward Extended in Google Developer Taipei
abc873693
 
PPTX
Dev307
建興 王
 
PPT
部門會議 960625 Leon
Leon Chuang
 
利用Signalr打造即時通訊@Tech day geek
Johnson Gau
 
怎樣在 Flutter app 中使用 Google Maps
Weizhong Yang
 
I os 01
信嘉 陳
 
容器驅動開發 - .NET Conf 2017 @ 台中
Andrew Wu
 
Introduction to MVC of CodeIgniter 2.1.x
Bo-Yi Wu
 
Visual studio 2012 與 asp.net 4.5 (新功能與開發介紹) 第一天
Gelis Wu
 
[GDG Kaohsiung DevFest 2023] 以 Compose 及 Kotlin Multiplatform 打造多平台應用程式
Shengyou Fan
 
ASP.NET Core 2.1設計新思維與新發展
江華 奚
 
猫粮快报
tbmallf2e
 
I os 02
信嘉 陳
 
Windows Mobile 多媒體應用程式開發
Chui-Wen Chiu
 
Osgi Intro
Ching Yi Chan
 
Responsive Web UI Design
jay li
 
常用开发工具介绍
haozes
 
[JCConf 2023] 從 Kotlin Multiplatform 到 Compose Multiplatform:在多平台間輕鬆共用業務邏輯與 U...
Shengyou Fan
 
Uliweb cheat sheet_0.1
modou li
 
Spring 2.x 中文
Guo Albert
 
Flutter Forward Extended in Google Developer Taipei
abc873693
 
Dev307
建興 王
 
部門會議 960625 Leon
Leon Chuang
 
Ad

More from LiviaLiaoFontech (9)

PDF
2021laravelconftwslides11
LiviaLiaoFontech
 
PDF
2021laravelconftwslides10
LiviaLiaoFontech
 
PDF
2021laravelconftwslides9
LiviaLiaoFontech
 
PDF
2021laravelconftwslides6
LiviaLiaoFontech
 
PDF
2021laravelconftwslides4
LiviaLiaoFontech
 
PDF
2021.laravelconf.tw.slides5
LiviaLiaoFontech
 
PDF
2021.laravelconf.tw.slides3
LiviaLiaoFontech
 
PDF
2021.laravelconf.tw.slides2
LiviaLiaoFontech
 
PDF
2021.laravelconf.tw.slides1
LiviaLiaoFontech
 
2021laravelconftwslides11
LiviaLiaoFontech
 
2021laravelconftwslides10
LiviaLiaoFontech
 
2021laravelconftwslides9
LiviaLiaoFontech
 
2021laravelconftwslides6
LiviaLiaoFontech
 
2021laravelconftwslides4
LiviaLiaoFontech
 
2021.laravelconf.tw.slides5
LiviaLiaoFontech
 
2021.laravelconf.tw.slides3
LiviaLiaoFontech
 
2021.laravelconf.tw.slides2
LiviaLiaoFontech
 
2021.laravelconf.tw.slides1
LiviaLiaoFontech
 
Ad

2021laravelconftwslides12