免费国产精品自在自线-91精品国产色综合久久久浪潮-99热久久免费频精品-国产精品国模在线观看-久久亚洲国产精品成人?V秋霞-久久国产一级A片免费播放-亚洲国产欧洲综合97久久-久久国产白嫩美女呻吟高潮

ARTICLE DETAIL

資訊詳情

深耕商務(wù)建站與企業(yè)官網(wǎng)運營的一線實戰(zhàn)洞察。

基于Vue3與Vite從零構(gòu)建前端通用工具庫

基于Vue3與Vite從零構(gòu)建前端通用工具庫 你有沒有經(jīng)歷過這種場景項目里有個 utils 文件夾里面的 isMobile 函數(shù)有三四種實現(xiàn)有的用正則有的拿 navigator.userAgent 去判斷還有的是三年前從舊項目里直接 copy 過來的。當(dāng)你想抽個公共模塊統(tǒng)一一下時發(fā)現(xiàn)這些實現(xiàn)之間還有各種微妙的差異根本不敢隨便動。這種“重復(fù)造輪子”的混亂狀態(tài)我忍了很長時間最后下定決心干脆自己從零搭一套可復(fù)用的前端通用工具庫把常用的函數(shù)、組合式 API、通用組件都規(guī)范化讓以后的新項目能直接裝上用不用再到處翻歷史代碼。這篇文章我會基于 Vue3 JavaScript配合 Vite 的庫模式從 0 開始搭建這樣一個工具庫完整展示項目的目錄結(jié)構(gòu)、核心代碼實現(xiàn)、打包配置、單元測試和發(fā)布流程。全程用 JS 而不是 TypeScript主要照顧到團隊里很多工程還是純 JS 技術(shù)棧不想為了一個工具庫額外引入類型編譯成本。適合那些想把手頭零散的 utils 方法沉淀成正式 npm 包的開發(fā)者也適合想搞懂 Vite 庫模式到底怎么用的人。讀完你不僅能跑通整個流程還能避開我在實際搭建中踩過的幾個坑。1. 先想清楚通用工具庫究竟要解決誰的什么問題1.1 工具庫解決的是“重復(fù)成本”而非“炫技”很多同學(xué)一提到自建工具庫第一反應(yīng)是“我要把 lodash 重新寫一遍”其實不是這么回事。工具庫的核心價值是降低重復(fù)成本這個成本包括三部分寫代碼的時間、找代碼的時間、維護代碼的時間。我見過一個團隊內(nèi)部有三個不同的項目都寫了 formatDate 函數(shù)每個函數(shù)的輸出格式還不完全一樣有的支持傳入連字符有的只支持斜杠。后來產(chǎn)品要求統(tǒng)一日期展示格式負(fù)責(zé)的老兄花了整整一個下午去改三套實現(xiàn)改完還不敢保證邊界情況全部覆蓋。如果當(dāng)初有一個統(tǒng)一維護的工具函數(shù)這個問題就是改一個文件、發(fā)一個新版、所有項目升級依賴這么簡單。但自建工具庫也不是毫無成本你需要配置構(gòu)建、測試、文檔、發(fā)布還要持續(xù)維護。所以正確的姿勢是先判斷“值不值得做”。我的判斷標(biāo)準(zhǔn)很簡單只要存在一個函數(shù)或組件連續(xù)出現(xiàn)在三個以上項目里并且它們的行為基本一致就值得沉淀進工具庫。如果只是當(dāng)前項目一處用到就先忍住別抽等第二次需要時再抽也不遲。1.2 什么代碼適合放進通用工具庫適合放進通用工具庫的代碼有這幾個共同特征無業(yè)務(wù)上下文、依賴外部環(huán)境少、可以獨立測試、結(jié)果可預(yù)期。以純函數(shù)為例日期格式化、千分位轉(zhuǎn)換、URL 參數(shù)解析、uuid 生成都非常適合。組合式 API 方面useWindowSize、useLocalStorage、useEventListener 這類也是天然的工具庫素材。通用組件就更多了比如可定制的高亮文本、懶加載圖片、防重復(fù)點擊按鈕等。不適合的典型例子是封裝了特定后端接口的 request比如帶了某個接口的鑒權(quán)頭、綁定業(yè)務(wù)權(quán)限的指令、只服務(wù)于當(dāng)前頁面布局的巨型組件。這些代碼一旦脫離當(dāng)前業(yè)務(wù)環(huán)境就廢了硬塞進工具庫只會讓維護者為了抽象這些業(yè)務(wù)邏輯而頭疼。還有一個容易忽略的判斷維度團隊成員的使用習(xí)慣。如果你建了一個工具庫但其他項目的人根本不用那就是在自娛自樂。所以我在動手之前專門拉了一個清單把日常代碼里重復(fù)出現(xiàn)的小函數(shù)都列出來先統(tǒng)計使用頻率再決定首批放哪些工具。這一步看起來簡單實際決定了工具庫后續(xù)的活躍度。另外說一下為什么選 Vue3 JS 而不直接上 TS。我自己項目里有相當(dāng)一部分是遺留的 JS 代碼如果工具庫用 TS 寫雖然能提供類型聲明但構(gòu)建鏈路會復(fù)雜一截而且會讓不愿意碰 TS 的同事產(chǎn)生距離感。Vue3 的組合式 API 本身對 JS 的友好度很高很多邏輯根本不需要類型系統(tǒng)就能表達(dá)得很清晰。當(dāng)然如果你的團隊全員 TS那直接用 TS 寫會更好——工具庫的選型永遠(yuǎn)跟著團隊現(xiàn)狀走不是跟著技術(shù)潮流走。2. 工程化骨架用 Vite 的庫模式搭出可發(fā)布的包2.1 初始化項目與基礎(chǔ)依賴新建一個工具庫項目最省事的方式是用 Vite 的腳手架保留 Vue3 模板。我用的命令是這樣的npm create vitelatest my-utils -- --template vue模板帶上的 React 之類的東西都可以刪掉我們只需要一個干凈的 Vite Vue3 環(huán)境。因為這個工具庫不是業(yè)務(wù)應(yīng)用所以入口不再是 index.html而是一個倉庫入口文件這點后面會重點說。依賴安裝上除了 vue 和 vite我還會加這幾個運行時無關(guān)的工具npm install -D vitest vue/test-utils eslint prettier husky lint-staged這里稍微解釋一下為什么需要這些。vitest 用來跑單元測試因為它是 Vite 生態(tài)的測試框架可以復(fù)用同一個 vite.config不用單獨配一套vue/test-utils 是 Vue 組件測試的官方工具庫測組件必用eslint 和 prettier 統(tǒng)一代碼風(fēng)格husky 和 lint-staged 負(fù)責(zé)在提交前攔截不規(guī)范代碼。對一個公共工具庫來說質(zhì)量門禁是必須的因為代碼一旦發(fā)布出去被多個項目依賴任何低級錯誤都會被無限放大。2.2 Vite 的 lib 模式配置解析Vite 默認(rèn)構(gòu)建的是應(yīng)用會從 index.html 出發(fā)生成一堆靜態(tài)資源。工具庫要的是“庫模式”——從一個 JS 入口開始把內(nèi)容編譯成可被其他代碼 import 的包。配置核心就落在build.lib上。我最終的 vite.config.js 是這樣寫的import { defineConfig } from vite import vue from vitejs/plugin-vue export default defineConfig({ plugins: [vue()], build: { lib: { entry: src/index.js, name: MyUtils, formats: [es, cjs, umd], fileName: (format) format es ? my-utils.esm.js : my-utils.${format}.js }, rollupOptions: { external: [vue], output: { globals: { vue: Vue } } } }, test: { environment: jsdom } })這里面的關(guān)鍵點值得好好說說。entry指向的是包入口工具庫所有對外暴露的能力都從這個文件導(dǎo)出。formats我選了 es、cjs、umd 三種ESM 適合現(xiàn)代打包器可以觸發(fā) tree-shakingCJS 是為了兼容舊版 Node 環(huán)境和老式構(gòu)建器UMD 則是給那些直接在 script 標(biāo)簽里引用的人用的雖然現(xiàn)在已經(jīng)很少見但加上總沒壞處。rollupOptions.external: [vue]是一個特別重要的配置。它告訴 Vite“vue 這個依賴不要打包進我的產(chǎn)物里?!币驗楣ぞ邘炖锏慕M件、組合式 API 都依賴 Vue但 Vue 應(yīng)該由使用方項目提供而不是工具庫重復(fù)打包一份。如果這里不排除發(fā)布出去的包體積會大很多而且可能導(dǎo)致使用方項目里同時存在兩份 Vue 實例觸發(fā)各種奇奇怪怪的問題。這點我在后面第 6 部分還會專門強調(diào)。2.3 目錄結(jié)構(gòu)設(shè)計JS 工具、組合式函數(shù)、組件分開維護工具庫不是把所有代碼堆在一個文件里就完事目錄結(jié)構(gòu)直接決定了后續(xù)的可維護性。我采用的是一套簡單清晰的分層模式my-utils/ ├── src/ │ ├── index.js # 入口統(tǒng)一導(dǎo)出 │ ├── funcs/ # 純函數(shù)工具 │ │ ├── formatDate.js │ │ ├── debounce.js │ │ └── ... │ ├── composables/ # 組合式 API │ │ ├── useWindowSize.js │ │ ├── useLocalStorage.js │ │ └── ... │ └── components/ # 通用 Vue 組件 │ ├── HighlightText/ │ │ ├── index.js │ │ └── HighlightText.vue │ └── ... ├── test/ # Vitest 測試用例 ├── dist/ # 構(gòu)建產(chǎn)物gitignore ├── package.json ├── vite.config.js └── ...為什么把純函數(shù)、組合式 API、組件分成三個目錄因為它們的用法和構(gòu)建路徑完全不同。純函數(shù)是普通 JS 模塊可以直接被任何環(huán)境加載組合式 API 依賴 Vue 的運行時但不需要渲染組件則必須有 Vue 的渲染器配合。分開后后續(xù)做按需引入時非常方便使用者可以精確地只加載一個模塊。入口文件src/index.js的作用是把所有能力匯總到一處方便全量引用。同時我也在 package.json 里配好了子路徑導(dǎo)出讓使用者既能import { debounce } from my-utils全量引入也能import debounce from my-utils/funcs/debounce精準(zhǔn)引入這其實就是按需加載的另一種手段后面詳細(xì)講。這樣一個骨架搭完你就有了一個干凈的起點。接下來最核心的事情就是往里面填充真正有用的代碼。3. 通用函數(shù)、組合式 API、組件三類能力的實現(xiàn)與設(shè)計思路3.1 純函數(shù)以 formatDate 和 debounce 為例純函數(shù)是工具庫的基本盤。寫這些函數(shù)的核心原則是輸入可預(yù)期、輸出穩(wěn)定、不做意外的事。我拿兩個最常見的例子展開。第一個是formatDate。很多項目都用 date-fns 或 dayjs但為了一個兩個格式化的需求去引整個庫其實有點重。自己寫一個針對常用格式的輕量函數(shù)就夠了// src/funcs/formatDate.js export function formatDate(date, fmt YYYY-MM-DD HH:mm:ss) { const d date instanceof Date ? date : new Date(date) if (Number.isNaN(d.getTime())) { throw new TypeError(formatDate received an invalid date) } const pad (n) String(n).padStart(2, 0) const map { YYYY: d.getFullYear(), MM: pad(d.getMonth() 1), DD: pad(d.getDate()), HH: pad(d.getHours()), mm: pad(d.getMinutes()), ss: pad(d.getSeconds()) } return fmt.replace(/YYYY|MM|DD|HH|mm|ss/g, (match) String(map[match])) }我特意沒有做很復(fù)雜的令牌解析只覆蓋了最常見的年月日時分秒為什么這么克制因為工具庫的代碼要盡可能容易被后續(xù)的人讀懂功能越多、邊界情況越多潛在的風(fēng)險就越大。當(dāng)實際需求超出這個范圍時直接按 dayjs 或者 date-fns 更合理不要試圖自己架一個完整的日期引擎。一個容易被忽略的細(xì)節(jié)入?yún)⒍x成date instanceof Date ? date : new Date(date)。這樣字符串日期、時間戳都能兼容并且當(dāng)傳入非法值時會顯式拋錯而不是返回一個又難看又難排查的NaN/NaN/NaN。顯式拋錯是工具代碼里值得推崇的做法——寧可讓調(diào)用方在開發(fā)階段就發(fā)現(xiàn)錯誤也不要把錯誤吞掉。第二個例子是debounce這個函數(shù)幾乎每個項目都自己寫過一版但很多版本在“取消”和“立即執(zhí)行”這兩個能力上是缺失的。工具庫里的 debounce 應(yīng)該更完整// src/funcs/debounce.js export function debounce(fn, wait 300, immediate false) { if (typeof fn ! function) { throw new TypeError(expected a function as first argument) } let timer null let result null const debounced function (...args) { return new Promise((resolve) { const later () { timer null if (!immediate) { result fn.apply(this, args) resolve(result) } } const callNow immediate !timer clearTimeout(timer) timer setTimeout(later, wait) if (callNow) { result fn.apply(this, args) resolve(result) } }) } debounced.cancel () { clearTimeout(timer) timer null } return debounced }這里有兩個設(shè)計點是我從實際項目里總結(jié)出來的。第一用 Promise 包一層讓調(diào)用方可以用await debounced()拿到函數(shù)返回結(jié)果這對手寫版 debounce 來說是不常見的但實際在某些需要等待結(jié)果入庫的場景特別好用。第二保留.cancel方法這樣在組件卸載時能優(yōu)雅地清理掉還未觸發(fā)的任務(wù)避免在異步回調(diào)里觸發(fā)對已卸載組件的操作。3.2 組合式 API封裝一個 useWindowSizeVue3 的組合式 API 非常適合做工具庫因為它能把響應(yīng)式狀態(tài)、副作用生命周期都管理起來。我用useWindowSize來示范一個標(biāo)準(zhǔn)寫法// src/composables/useWindowSize.js import { ref, onMounted, onUnmounted } from vue export function useWindowSize() { const width ref(window.innerWidth) const height ref(window.innerHeight) const update () { width.value window.innerWidth height.value window.innerHeight } onMounted(() { window.addEventListener(resize, update) }) onUnmounted(() { window.removeEventListener(resize, update) }) return { width, height } }為什么用ref而不是reactive因為返回的是一個雙成員對象用 ref 包裹后使用方可以優(yōu)雅地解構(gòu)const { width, height } useWindowSize()同時這兩個值在模板里可以直接渲染不會丟失響應(yīng)性。而如果用 reactive 包裝解構(gòu)后響應(yīng)性就斷了。監(jiān)聽事件一定要放在onMounted里嗎不一定如果你的工具庫只會在組件實例中調(diào)用那么 onMounted 是安全的。但如果你希望這個函數(shù)也能在普通 JS 環(huán)境沒有組件上下文下使用那就需要做一些兼容處理比如直接用const update () {...}然后立即初始化再返回一個手動銷毀的方法。我這里的寫法是為絕大多數(shù) Vue 單文件組件場景設(shè)計的簡單可靠。需要額外說明的是組件的onUnmounted保證了 resize 監(jiān)聽器在組件銷毀時被移除這能避免大多數(shù)內(nèi)存泄漏問題。再多說一點工具型的 composable 最重要的是“副作用可控”。類似useWindowSize這種監(jiān)聽一個全局事件就必須在合適時機解綁絕不能讓使用方背著內(nèi)存泄漏的債。3.3 通用組件從最簡單的高亮文本組件開始通用組件是工具庫里比較容易“膨脹”的部分因為 UI 設(shè)計千差萬別強行做成通用往往兩頭不討好。我建議從沒有視覺綁定的功能型組件開始比如高亮文本。它負(fù)責(zé)接收關(guān)鍵詞把匹配到的片段用mark或其他標(biāo)簽包起來至于樣式直接由使用方的項目控制。用 Vue3 的 SFC 和 JS 實現(xiàn)如下!-- src/components/HighlightText/HighlightText.vue -- template span classmy-utils-highlight-text template v-for(part, index) in parts :keyindex {{ part.text }}slot v-ifpart.match namehighlight :partpart{{ part.text }}/slot /template /span /template script setup import { computed } from vue const props defineProps({ text: { type: String, required: true }, keyword: { type: String, default: }, caseSensitive: { type: Boolean, default: false } }) const parts computed(() { if (!props.keyword || !props.text) { return [{ text: props.text || , match: false }] } const flags props.caseSensitive ? g : gi const regex new RegExp((${escapeRegExp(props.keyword)}), flags) return props.text .split(regex) .filter((segment) segment ! undefined) .map((segment, index) ({ text: segment, match: regex.test(segment), index })) }) function escapeRegExp(str) { return str.replace(/[.*?^${}()|[\]\\]/g, \\$) } /script組件可以配合插件式注冊實現(xiàn)全量引入// src/components/HighlightText/index.js import HighlightText from ./HighlightText.vue export default HighlightText然后在主入口里注冊// src/index.js export { default as HighlightText } from ./components/HighlightText/index.js組件本身不綁定任何樣式由使用方項目用樣式覆蓋這是保持通用性的關(guān)鍵。如果你在組件里寫死了背景色和字體到每個項目里都會有人抱怨“顏色對不上”。這里的關(guān)鍵詞匹配我特意用正則做了轉(zhuǎn)義避免用戶輸入*或.等正則特殊字符導(dǎo)致匹配行為異常。高亮文本組件規(guī)模不大但它演示了工具組件最基本的設(shè)計思路props 傳入數(shù)據(jù)、不依賴業(yè)務(wù)狀態(tài)、支持插槽做擴展、無內(nèi)置樣式。后續(xù)要擴展其他組件時都可以參考這個模式。4. 質(zhì)量保障ESLint Prettier Vitest 讓工具庫少踩坑4.1 ESLint 與 Prettier 配置要點工具庫代碼會被很多人依賴代碼風(fēng)格不統(tǒng)一會直接導(dǎo)致合并沖突和 review 效率低下。我在項目里集成了 ESLint 和 Prettier配置比較簡單但夠用。// .eslintrc.cjs module.exports { root: true, env: { browser: true, node: true, es2022: true }, extends: [ eslint:recommended, plugin:vue/vue3-essential, prettier ], parserOptions: { ecmaVersion: 2022, sourceType: module }, rules: { vue/multi-word-component-names: off } }vue/multi-word-component-names這個規(guī)則默認(rèn)要求組件名必須是多個單詞但對于工具庫來說很多通用組件就是HighlightText、DebounceButton這種兩詞名字也有個別像Button這種基礎(chǔ)組件所以關(guān)掉比較省心。Prettier 簡單配置一個.prettierrc{ semi: false, singleQuote: true, trailingComma: none, printWidth: 100 }因為主要是 JS 文件行寬設(shè) 100 足夠。把 ESLint、Prettier、Vite 同時跑通的好處是代碼風(fēng)格不再需要人工 review機器幫你兜底。4.2 給工具庫補上單元測試Vitest工具庫是純邏輯居多不測一下說不過去。Vitest 和 Vite 深度集成跑測試直接用vitest命令就行。我寫幾個典型測試// test/formatDate.test.js import { describe, it, expect } from vitest import { formatDate } from ../src/funcs/formatDate describe(formatDate, () { it(formats date correctly, () { const date new Date(2024, 0, 15, 9, 30, 45) expect(formatDate(date)).toBe(2024-01-15 09:30:45) }) it(throws on invalid date, () { expect(() formatDate(not-a-date)).toThrow(TypeError) }) })debounce 的測試需要依賴 fake timersVitest 同樣支持// test/debounce.test.js import { describe, it, expect, vi } from vitest import { debounce } from ../src/funcs/debounce describe(debounce, () { it(waits until wait time passes before invoking, () { vi.useFakeTimers() const fn vi.fn() const debounced debounce(fn, 200) debounced() vi.advanceTimersByTime(100) expect(fn).not.toHaveBeenCalled() vi.advanceTimersByTime(100) expect(fn).toHaveBeenCalledTimes(1) vi.useRealTimers() }) })組合式 API 的測試稍微復(fù)雜一點需要提供一個宿主環(huán)境。Vitest 開了environment: jsdom后我們可以用vue/test-utils掛載一個小組件來驗證// test/useWindowSize.test.js import { describe, it, expect, vi } from vitest import { mount } from vue/test-utils import { defineComponent, h } from vue import { useWindowSize } from ../src/composables/useWindowSize describe(useWindowSize, () { it(returns window dimensions, async () { const Comp defineComponent({ setup() { const size useWindowSize() return () h(div, ${size.width.value}x${size.height.value}) } }) window.innerWidth 1024 window.innerHeight 768 const wrapper mount(Comp) expect(wrapper.text()).toBe(1024x768) window.innerWidth 1280 window.dispatchEvent(new Event(resize)) await wrapper.vm.$nextTick() expect(wrapper.text()).toBe(1280x768) wrapper.unmount() }) })這種測試的意義是保證核心函數(shù)的行為回歸可控。工具庫一旦發(fā)布任何一次升級都可能影響很多項目沒有測試誰敢隨便升版本所以我個人的建議是工具庫里的每個函數(shù)至少一個主流程測試加一個邊界測試每個 composable 至少測掛載和銷毀組件至少測 props 渲染。4.3 lint-staged husky 攔截不規(guī)范的提交有了 ESLint 和測試還需要把它們卡在提交前否則總有人跳過檢查。簡單搭一個 husky 鉤子npx husky init然后配置lint-staged在 package.json 里{ lint-staged: { *.{js,vue}: [eslint --fix, prettier --write] } }同時.husky/pre-commit里寫npx lint-staged這樣每次提交只會檢查暫存區(qū)里的文件速度很快也不會逼著大家把所有測試跑一遍。更嚴(yán)謹(jǐn)點的團隊可以在 pre-push 階段跑全量測試但工具庫代碼量不大所以我在 commit 前直接跑了npm test npm run lint也行。質(zhì)量門禁的意義不在于設(shè)置多少關(guān)卡而在于讓團隊所有人都保持一致的習(xí)慣。5. 打包與發(fā)布從本地工具庫到 npm 公共包5.1 多格式產(chǎn)物與 Tree ShakingVite 庫模式在build后會在 dist 目錄下生成三個文件my-utils.esm.js、my-utils.cjs.js、my-utils.umd.js。ESM 文件內(nèi)部使用 ES Module 語法現(xiàn)代打包器Vite、webpack 5、Rollup在解析 import 時可以靜態(tài)分析導(dǎo)出成員從而剔除未使用的代碼這就是 tree-shaking 的基礎(chǔ)。要讓 tree-shaking 真正生效package.json 里必須明確sideEffects: false意思是這個包里的模塊都沒有副作用。但組件文件可能包含樣式副作用所以如果你有 CSS需要單獨處理。我的做法是把組件樣式內(nèi)聯(lián)到組件里用style scoped這樣 Vite 在編譯后會把 CSS 抽離成單獨的 CSS 文件在 package.json 里通過sideEffects指定 CSS 文件有副作用其他模塊沒有。目前我們先不引入 CSS保持sideEffects: false是最省心的。5.2 package.json 的關(guān)鍵字段構(gòu)建產(chǎn)物出來后發(fā)布配置是重中之重。我最終的 package.json 關(guān)鍵字段長這樣{ name: my-utils, version: 0.1.0, description: A collection of Vue3 JS utilities, composables and components, type: module, main: ./dist/my-utils.cjs.js, module: ./dist/my-utils.esm.js, unpkg: ./dist/my-utils.umd.js, exports: { .: { import: ./dist/my-utils.esm.js, require: ./dist/my-utils.cjs.js }, ./funcs/*: ./dist/funcs/*.js, ./composables/*: ./dist/composables/*.js, ./components/*: ./dist/components/*.js }, files: [dist, README.md], peerDependencies: { vue: 3.2.0 }, sideEffects: false, scripts: { build: vite build, test: vitest run, lint: eslint src test --fix } }幾個字段解釋一下。main指向 CJS 產(chǎn)物是為了兼容還沒有切換到 ESM 的舊 Node 環(huán)境。module指向 ESM 產(chǎn)物現(xiàn)代打包器會優(yōu)先讀取。exports字段是 Node.js 12 和現(xiàn)代打包器的新標(biāo)準(zhǔn)它比 main/module 更精細(xì)能限制外部訪問包內(nèi)未聲明的路徑防止別人import my-utils/src/xxx這種奇怪的引用方式。files決定發(fā)布時哪些文件會被打進 npm 包這里只包含 dist 和 README能有效避免把源碼、測試文件全部發(fā)布出去既縮小包體積也避免暴露未編譯的內(nèi)部細(xì)節(jié)。peerDependencies用來聲明這個包依賴的宿主版本——Vue 3.2 及以上但不會把 Vue 安裝進來。在發(fā)布前建議先本地驗證一下npm pack這會生成my-utils-0.1.0.tgz你可以解開看看里面有什么再或者用一個臨時項目npm install /path/to/my-utils-0.1.0.tgz實際引用一下確保發(fā)布到 npm 后不會出現(xiàn)“裝回來發(fā)現(xiàn)缺文件”的尷尬。5.3 版本號與更新日志別讓發(fā)布變成災(zāi)難工具庫的版本管理我強烈建議走語義化版本SemVer也就是MAJOR.MINOR.PATCH。新增一個向后兼容的函數(shù)升 MINOR修復(fù)原有函數(shù)的 bug升 PATCH如果你改了函數(shù)入?yún)?、調(diào)整了組件 props 的必填項這類破壞性變化一定要升 MAJOR。配合 conventional commits可以在每次提交時自動生成 CHANGELOG。比如feat: add useLocalStorage會被識別為 feature 更新fix: correct formatDate timezone offset會被識別為 bug 修復(fù)。我在項目里用了standard-version這個工具來根據(jù)提交記錄自動生成版本號和 changelog執(zhí)行npx standard-version就會自動修改 version、生成 CHANGELOG.md、打上 git tag非常省事。不過版本生成的粒度還是要自己控制。工具庫的發(fā)布頻率不宜太高我一般會在一次功能迭代完成后集中發(fā)布一版而不是每次 commit 都發(fā)。多個項目共用一個工具庫的好處也體現(xiàn)在這里——只有你的版本規(guī)劃做得足夠清晰下游項目才能放心地跟進升級。6. 實戰(zhàn)中繞不開的坑記住了能省下半天時間6.1 Vue 外部化后別忘了開發(fā)依賴?yán)锏?vue前面說了打包時要把 Vue 設(shè)為 external但很多新手會掉進另一個坑既然 vue 是 peerDependencies是不是項目里就不用裝 vue 了不是的。你本地開發(fā)工具庫時仍然需要 vue 作為 devDependency因為組件和測試都要實際運行。peerDependencies 解決的是“使用方要自己裝 vue”而 devDependencies 解決的是“你在開發(fā)這個庫時需要 vue 可用”。我見過一個例子某位同事把 vue 從 devDependencies 里刪掉認(rèn)為發(fā)布時會自動帶上結(jié)果本地跑測試直接報“Cannot find module ‘vue’”。正確的習(xí)慣是vue 同時出現(xiàn)在 peerDependencies 和 devDependencies 里peer 里寫寬松范圍如3.2.0dev 里寫一個明確的版本保證本地開發(fā)環(huán)境可控。6.2 Tree Shaking 對組件并沒有想象中那么靈組件跟純函數(shù)不一樣。如果你在主入口 index.js 里一次性導(dǎo)出了 10 個組件然后使用方通過import { Button } from my-utils這樣的方式按需引用現(xiàn)代打包器確實可以通過 tree-shaking 把沒用到的組件代碼丟掉。但這里有個前提組件內(nèi)部不能被任何模塊級副作用觸發(fā)比如組件文件頂部直接插入全局 CSS 或執(zhí)行console.log。更讓人頭疼的是如果使用方項目用 webpack 4 這類對 tree-shaking 支持不完善的老構(gòu)建器一個入口導(dǎo)出很多組件反而可能導(dǎo)致全部被打進 bundle 里。這時候你就需要子路徑導(dǎo)出讓使用方可以import Button from my-utils/components/Button這樣的精確引用繞開 tree-shaking 的機制限制。這也是我在 package.json 里配置 exports 子路徑的初衷——為老舊項目留一條后路。6.3 發(fā)布前務(wù)必先本地聯(lián)調(diào)最好用 npm link 或 yalc我最后一次發(fā)布的教訓(xùn)是“發(fā)布一時爽打完臉就腫”。那次我更新了一個組件里的 prop 默認(rèn)值本地構(gòu)建和測試都通過了直接npm publish結(jié)果有個項目升級后組件的樣式全亂了。原因是我漏改了另一處相關(guān)代碼但本地沒有實際業(yè)務(wù)場景測試也沒有覆蓋到所有 CSS 組合。從那以后我養(yǎng)成了發(fā)布前先用npm link或者yalc把包鏈接到實際項目里做冒煙驗證的習(xí)慣。npm link的用法很簡單在工具庫目錄里執(zhí)行npm link再在目標(biāo)項目里執(zhí)行npm link my-utils這樣目標(biāo)項目引用的就是本地源碼產(chǎn)物改動后的效果能立即看到。但 npm link 會改變 node_modules 的符號鏈接結(jié)構(gòu)偶爾會觸發(fā) vite 緩存問題所以我個人更喜歡 yalc——它會把本地發(fā)布文件“推”到目標(biāo)項目的 node_modules 里更接近真實依賴情況也不會因為符號鏈接導(dǎo)致某些工具無法解析。說到底工具庫開發(fā)的完整閉環(huán)是“編碼 - 測試 - 構(gòu)建 - 本地聯(lián)調(diào) - 發(fā)布”。前四步走得越扎實最后一步就越穩(wěn)。每當(dāng)我偷懶跳過本地聯(lián)調(diào)時幾乎都會在下一次發(fā)布后收到一個“有問題”的反饋。所以現(xiàn)在我的出包流程里npm pack和本地冒煙這步已經(jīng)成了肌肉記憶。從我這次搭建工具庫的經(jīng)歷來看最耗時間的不是寫那幾十個函數(shù)而是讓整個項目變得干凈、可信、可維護的過程。工具庫的本質(zhì)是給未來的自己和其他項目“預(yù)寫”代碼如果你的包發(fā)布一次就要讓下游項目改一次配置那這個工具庫就失去了意義。如果你也打算動手我的建議是從一個最小的函數(shù)庫開始先跑通打包發(fā)布流程再逐步加入組合式 API 和組件別一開始就想面面俱到。最后再分享一個小技巧每次構(gòu)建之后進 dist 目錄隨便打開一個產(chǎn)物文件看看里面有沒有意外的殘留代碼比如過期的注釋、調(diào)試用的 console 語句——有一次我就在產(chǎn)物里發(fā)現(xiàn)了一段被誤加到純函數(shù)里的 console.warn還好發(fā)的是預(yù)發(fā)布版本沒有影響線上項目。這種細(xì)節(jié)點滴積累起來就是工具庫和其他人的隨手分享之間最大的區(qū)別。
返回列表
PREV
查看更多資訊
NEXT
返回資訊列表
五月天婷婷激情在线色图| 亚洲午夜国产成人电影VA国产欧…| 午夜一区| 99久久高清视频| 婷婷伊人综合中文字幕| 99爱视频免费看| 五月丁香操婷逼| 国外亚洲成AV人片在线观看| 丁香六月啪| 六月婷婷狠狠做| 久青操| 黑人巨粗进入警花疼哭A片| 九九热在线观看视频| 99在线观看视频免费| av婷婷丁香| 日本色五月| 噜噜噜噜噜在线| 天天拍天天操| 操九色| 天天草天天爱| 亚洲欧洲99| WWW.HENHENL.| 日本韩国视频在线观看社区免费的9| www.色擼擼.com| 日韩av在线电影| 人妻免费网站| www.91五月| 亚洲av骚货| 99热这里只有精品2| 五月婷婷激情四季| se99高清无码| 日韩欧美五月丁综合| AV网在线观看| 丁香五月最新网址| 综合激情伊人影视在线| 97在线视频人妻九色| 超碰99在线| 婷婷五月天免费小说| 五月色婷婷夜色| 99热99色| 操一区| 丁香五月综合激情啪啪| 99久精品视频| 五月婷视频| 久久这里只有精品1| 婷五月丁香俺| 人人舔人人色人人高潮| 亚洲久久视频| 久久精品视频99| 996热re视频在线观看视频| 激情婷婷五月天| 色你久久| 五月天丁香网| 九热视频| 五月Huangsewang| 国产激情视频在线观看| 精品人妻午夜一区二区三区四区| 狠狠婷婷色| 粉嫩AV久久一区二区三区| 欧美色五月| 婷婷五月无码| 亚洲视频另类| 大香人妻| 日韩在线一级| 99精品热视频| 五月婷婷伦理| 玖操97| 天天干天天操天天上| 成人色色综合| 五月婷婷六月爱| 丁香五月婷婷色综合| 九九久久高清| 综合99久久天天综合| 婷婷色一二三区波多野结衣| 99无码超碰| 五月丁香色色网| 嫩草AV久久伊人妇女超级A| 色色色无码| 99热免| 欧美日韩成人在线网| www.日本91| 超碰99热精品| 操操啪| 桃色成人网| 激情玖玖sh| 嫩模草| 日本9区视频| www一起操| 国产三级片91| 人妻久久久久久久| 啪啪啪丁香五月| 在线成人av播放| 91九色精品| 超碰成人电影| 热这里| 色婷婷五月网| 五月WWW| 激情五月婷婷五月丁香五月开心五月| 久久久99久久| 天天色中文字幕女优AV| 色播色丁香五月| 九九综合网色全集| 婷婷五月丁香狠狠| 国产精品视频| 欧美综合五月天婷婷tin| 丁香色情五月综合激情| 婷婷伊在线| 热的无码综合视频| 小视频久久久aaa| 少妇出轨做爰高潮A片| 日韩啪图| 2025中文在线视频字幕免费观看| 精品人妻一区二区| 欧美搡BBBBB摔BBBBB| av在线免费播放观看| 丁乡久久| 嫩草AV久久伊人妇女超级a| 久久婷婷五月天| 激情99| 亚洲av综合在线| 久久人人超| 丁香五月婷婷六月婷| 婷婷亚洲欧美丁香五月| 亚洲无AV在线中文字幕| 激情中文在线| 九九色逼| 99热线观看9| A一级操| 五月天婷婷爱| 国产真人做爰视频免费| 色色色色色热| 精品人妻在线| 96性爱视频| 成人亚洲精品久久久久 | 日操| www久久99| 五月婷狠狠| 9久热| 五月亭亭性| 九九热最新视频| 手机旧版看人妻1025| www五月| 色婷婷九月| 99网| 五月亭亭六月色| www.五月.com| 五月大香蕉| 99热99日天天干| 天天日夜夜高潮| 亚洲五月丁香六月婷婷| 1囯产午夜仑鲁鲁| 五月丁香六月合| 大香蕉久| 五月天社区| 色综合色色| 青草视频在线观看视频| 色欲操| 99久视频| 五月亭亭欧美女人| 五月丁香婷婷深深爱| 97涩婷婷| 五月丁香六月婷婷激情视频在线观看免费 | 男人的天堂五月丁香| 久久se 综合网 | 99色热视频| 婷婷综合激情| 色色99色色| 色色色色网站| 色婷五月婷婷| 丁香五月影院| 激情综合五月婷| 99色色爰| 亚洲成人人人操| 婷婷狠狠干| 色色色色色五月丁香| 怡红院视频| 五月婷婷影视| 亚洲色网址| 五月丁香A片| 九九热短视频在线观看 | 欧美日本黄色| 婷婷99狠狠躁天天躁中| av激情在线| 青草激情在线| 五月婷婷天天| 超碰色天堂| 激情五月天伊人影院| 国内精品免费一区二区2009| www.minyis.com【JT】币址百万U预算可预付QQ2101460746 | 色香蕉精品五夜婷| 五月情涩综合婷婷| 五月丁香六月婷婷久久| 九九色综合九九色| 亚洲最大在线| 色婷丨日丨天丨综合久久| 五月婷婷久久综合| 人色五月天婷婷| 国外亚洲成AV人片在线观看| 人妻精品久久久久久久| 天堂久久性| 夜夜爽天天爽| 大香蕉久久伊人婷婷五月丁香| 欧美色婷婷| 精品99这里有| 神马久久五月天| 亚洲色色精品| 婷婷色在线播放| 国产免费一区二区三区三州老师F1F1.CC| 九九精品热播| 99热精品在线观看| 99热这里只有精品86| a片在线免费观看一区| 婷婷五月天网| 丁香五月天色综合| 久久人妻www| 996黄色片| 少妇性按摩无码中文A片| 成人综合视频在线| 国产看真人毛片爱做A片| 99爱免费视频| 日本69日人视频| 国产成人精品一区二区三区视频 | 五月天婷婷在线AN| 久久视这里只有精品| 激情欧美五月丁香| 五月天欧美 另类小说| 久久婷婷网址| 五月天激情久久| 日本在线噜噜| 欧美丁香五月| 欧美日本免费一道免费视频| 97热精品| 99爱免费视频| 亚洲日本激情| 亚洲成人在线综合| 久久婷婷丁香| 色五月首页| 丁香婷婷五月色综合| 狠狠爱婷婷| 色婷婷成人在线| 亚洲啪啪精品| 无人区码一码二码三码医生系列| 丁香婷婷六月天| 婷婷五月天伊人网在线观看视频| 96丁香六月婷婷蜜桃综合久久| 99∨VTV| A网在线欧洲| 狠狠爱激情网| 九九99视频精品| 五月天社区| 日日夜夜天天爽| 天天操婷婷| 伊人网色婷婷五月天| 97久久超碰| 91色色色视频| 99久热| 噜噜噜久久| 丁香婷婷六月激情| 大香蕉520| 97超碰色| 久久婷婷五月天丁香| 91操人| 丁香五月婷婷在线视频| 亚洲另类在线观看| a色婷婷| 91色性感五月婷婷丁香| 中文字幕在线免费看线人| 天天日日夜夜| 思思热AV| 激情网综合| 人妻爽爽爽久久久久久久久| 九九热超碰| 色色丁香五月天社区| 极品人妻VIDEOSSS人妻| 五月香婷婷| 99九九视频| 天干夜夜操| 99热综合在线观看| 婷婷激情蜜桃玖玖丁香| www.色婷婷。com| 丁香九九九九| 超碰AV成人| 日本人人超碰| 欧洲电影在线观看免费版英语版| 开心激情站| 婷婷操逼| 五月丁香色婷婷| 9有码中文| 五月综合无码| www、丁香五月天| 亚洲一二三网| 肏日网在线看| 日本九九九九九九| 人妻中文字幕网| 婷婷五月天渟渟| 丁香五月激情图片婷婷| 91怕怕网| 丁香五月777| 国产精品岛国片在线观看免费| 激情精品久久| 九九九九九九九九九九九九九国产精品| 五月天丁香婷婷视频网址| 激情六月婷婷| 无码AV免费精品一区二区三区| av中文在线| 99碰碰| 亚洲色五月| 被男人添B超爽视频| 亚洲激情AV| 日韩成人精品中文字幕| 日韩性爱AV| 日韩黄色中文字幕| 五月婷久久综合| 大香蕉丁香婷婷| 婷婷六久久| 婷婷五月天丁香综合网| 丁香婷婷色九月| 激情人妻综合| 五月噜噜噜色综合| 婷婷五月天亚洲精品| 久草xx性爱视频| 2025最新亚洲激情在线| 色播婷婷五月天| 亚州精品久久久久AV无码| 五月香六月婷| 色色色色综合网| 久9热视频在线观看| 亚洲视频二区| 99色在线观看视频| 五月香婷婷| 久久爱婷婷| 天天日夜夜爽| 五月花婷婷| 色噜噜狠狠色综无码久久合欧美| 日日操夜夜操中国无码| www.91操| Jh7Uf088VHafNm| 国产精品香蕉| 欧美成人A片AAA片在线播放| av中文在线| 在线成人va| 色色色色色日韩午夜激情 | 亚洲成人电影在线免费观看| 久99久在线观看| 思思热国产视频| 六月色色婷婷| 中文字幕av久久爽一区| 五月综合激情久久| 日本色图综合| 久久机热思思热| 日本久热| 成人久碰| 免费视频舔| 99热99干| 色优久久| 九九色院| 99欧美热| 99久热在线精品| 六月婷婷国产| 激情五月天色色网| 色综合视频| 欧洲婷婷五月天| 婷婷五月激情天| 五月色丁香| 国产高清视频91九九九久久久| 九九99免费理论| 六月婷婷狠狠做| 大香蕉久热| www.99热国产| 大功率国产在线| 99精品大片| 99综合网| 久久久激情视频| 99爱无码| 国产亚洲成AV人片在线观黄桃| www91在线| 99热这里只有精品69| a在线观看| 亚州成人综合在线| 六月丁香婷婷色综合| 婷婷综合视频| 久久五月天免费网站| 婷婷丁香高潮了| 综合激情在线| 亚洲欧美成人在线观看| 色色综合色视频| 777色色色| 538在线精品| 狠狠色狠狠| 婷婷丁香五月综合网上| 伊人网色婷婷五月天| 深爱激情中文五月天av| 精品激情| 色一情一乱一乱一区91| 五月天天综合| 99久久性爱| 中文字幕日产A片在线看| 欧亚洲在线高清视频| 人人视频色| 日日夜夜天天| 婷婷免费成人视频| 五月婷婷激情网| 日韩影院三级| 成人视频一区| 操91| www.婷婷.com| 日韩欧美颜射| 五月丁香人妻| 丁香五月精品视频| 婷婷五月天小说| www.91操| 久久婷婷综合五月天| 骚五月婷婷| 五月婷婷69| 色一情一乱一伦一区二区三区| 这里只有精品视频222| 51XX午夜影福利| 激情久久 婷婷| 国产偷人妻精品一区| 亚洲啪啪精品| 2020日日干| 五月天停婷基地| 激情五月天com| 99热精品网| 五月婷婷之综合激情| 六月丁香五月婷婷| 欧亚洲在线高清视频| 日韩啪啪视频| 狠狠干天天内射| 丁香五月激情五月| 青青福利网| 天天日中文| 99爱在线| 五月花亭亭| 99欧美精品99日本精品| 天天草比天天爽| www网站在线观看| 思思热在线精品视频| 免费亚洲成人电影AV| 色婷婷国产精品综合在线观看| 人人操人人干AV| 色综合丁香婷婷| 99热99色| 嫩草AV久久伊人妇女超级A| 六月天六月婷| 日本久久9| 九九99热| 高清视频一区| 国产人妻人伦精品一区二区| 午夜国产精品AV在线播放| 超碰成人影视| 黄网免费观看| 婷婷亚洲丁香五月| 亚州精品成人片| XX久久| 婷婷五月亚洲激情| 五月天啪啪网| 久九色| 婷婷五月天激情综合| 日本色啪| www.久久久.com| 99丁香五月婷| 久久久婷婷色五月资源网| 99热亚洲| 色五月激情综合| 超碰中文字幕在线| 99精品无码| 综合网五月天123| AV动漫不卡无码免费| 激情六月婷婷| 成人丁香五月天| 日良久久| 丁香五月激情啪啪啪啪| 婷婷五月蜜桃成人桃色丁香| 亲子乱AV-区二区三区| 操日视频| 亚洲中文乱字字幕线在永久| 色综合综合色| 美女婷婷激情亚洲| 五月婷六月| 五月丁香欧美在线| 華人性愛AV在線| 色婷婷久久9.com| 91丨九色丨大屁股| 丁香六月婷婷色XXXXX| 色婷婷手机在线| 欧美色必爱| 99热9| 夜夜夜夜夜操| 婷婷激情鹿城五月天| 久久 无毛。| 亚洲精品字幕| 色综合久久久久| 久久机热这里只有精品| eeuus五月婷| www.久9| 亚洲欧美在线观看| 亚洲天堂99| 五月丁香婷婷综合激情基地| 九九人人操| 日韩精品一区二区刘| 91狠狠色丁香婷婷综合久久| 九九色色网| 色色色色色色色综合| 五月天婷婷AV| 五月丁香狠狠爱婷婷综合| 色中色综合| 丁香婷五月天开心六月| 丁香婷婷成人在线播放| 亚洲综合丁香五月| 性色欲情 网站| 日韩另类在线观看| 啪啪五月综合| 日本97人人| 丁香婷五月| 国产视频福利| 超级碰91| 99热一本| 婷婷六月丁综合| 国产精品色情AAAAA片软件| 亚洲色久| 草婷婷在线| 色婷婷天堂| 丁香婷婷中文字幕| 天天日夜夜夜操操操操| 五月丁香激情综合| 天天色图| 噜噜噜狠狠色综| 色综合综合综合| 亚洲综合激情五月久久| 亚洲欧美成人在线| 五月天综合| 久热大香蕉| 久久99激情| 婷婷丁香五月激情| 天天搞天天爽| 日日夜夜干| 久久久久人妻精品| 99狠狠操一| 91色情播放| 激情网综合| 18av天堂| 日韩成人五月天| 伦乱美欧| 亚洲婷婷丁香五月视频| 五月WWW| va婷婷在线免费观看| 六月丁香深深爱| xx色综合| 开心婷婷五月花| 色色婷| 天天激情5月天亚洲| 婷婷色婷婷亚洲成人| 永久无码色| 天天摸天天舔在线视频| 米奇激情婷婷| 天天操夜夜橾| 天堂草在线看www| 五月天综合在线观看| 思思久久99| 九热免费视频| 色婷视频| 婷婷五月性感| 色婷成人狠干| 啪啪啪综合网| 那里有AV网址| 婷婷五月久久| 亚洲操操操| 99色综合网| 婷综合| 在线不卡视频| 另类婷婷五月天啪帕帕| 大香久久综合网| 色月丁| 五月婷婷激情| 五月情综合| 激情婷婷五月基地| 久久伦乱| 大地资源色婷婷视频在线| 六六久久黄色| 久草 天堂| 天天摸天天爽| 99综合| 色色操| 欧美69久成人做爰视频| 超碰97久久| 人妻射精AV| 天天色月| 九九在线精品| 五月丁香A片| 婷婷激情五月天综合| 色天天综合天天综合频道。| 韩国久久少妇视屏| 亚洲视频二区| 色五月亚洲| 五月天婷综合| 六月婷婷无码观看| 呦呦v线| 天天干天天插| 久久er99热精品一区二区 | 蜜臀99久久精品久久久久| 五月天激情日色在线| 五月婷婷av| 丁香五月网在线观看| 国产综合色婷婷精品久久| 亚洲精品一区无码A片| 久久婷婷夜| 久久婷婷丁香五月一二三| 婷婷六月激情丁香| 久久永久视频| 热久久这里只有三级视频| 91久久婷婷| 99热网站| 婷婷爱五月天| 99干99| 涩涩五| 色婷婷色99国产综合精品| 丁香婷婷久久五月天| 激情综合五月婷| 99热这里只有精品1| 丁香婷婷综合激情五月色| 色私五月婷婷| 天天干夜夜想| 春色激情| 涩综合在线| 影视av久久久噜噜噜噜噜三级| 久久精品一区二区三区四区| 96自拍视频九色在线观看| 日本综合久| 五月丁香六月婷婷的女人| 日韩啊啊啊| 婷婷丁香视频| www.五月瑟| 六月丁丁香| 久草视频一,二三四| 五月丁香基地| 久久五月视频| 国产操碰| 六月撸婷婷| 少妇水多A片太爽了| 性爱综合网| 丁香婷婷性久久| 欧美成人精品A片免费一区99| 91精品久久久久久久| 天天摸天天做天天爱天天爽| 九九無妻| 51XX午夜影福利| 人人操人人爰人人一天天碰夜夜拍夜夜爽-中国A级毛片天天看天天谢… | 天天干夜夜欢| 日韩精品AV一区二区三区| 操比激情五月综合| 天天人人人人人人人人人人人| 丝袜熟女一区二区三区| 丁香五月天导航| 国产精品久久..4399| 日熟女| 五月天激情婷婷| 欧美人人超级碰| 婷婷婷婷色| 久久久国产精品黄毛片| 亚洲五月天伊人| CHINESE熟女老女人HD视频 | 色婷视频| 亚洲成人中心| 激情综合色图| 亚洲成人在线免费| 香蕉久久国产AV一区二区| 久久婷婷亚洲| 久久人妻久久久久| 在线99热| 五月婷婷,六月激情| 色五月激情网| 激情婷婷丁香色情五月天| 国产成人精品一区二区三区视频| 成人Av在线大片| 激情五月天小说| 色色丁香五月天社区| 久久久这里有精品| 丁香密臀AV激情网| 99在线69| 99re熱| 亚洲国产精品二二三三区| 超碰精品手机在线| 欧美搡BBBBB摔BBBBB| 亚洲五月天第一综合干| 久草热8精品视频在线观看| 六月丁香激情综合| 欧美久人人| 丁香五月区| 五月丁香日本一抹本| 国产又黄又爽又色的免费| 人人干AV| 9l视频自拍九色9l视频在线观看| 99在线精品观看99| 综合激情网| 五月天婷婷无码| 五月婷丁香亚洲| 丁香五月天婷婷大香蕉| 精品久久9| www色婷婷久久综合久色 | 一本久久亚洲五月婷婷| 色婷婷av综合网| 久热亚洲| 99热这里有精品首页10| 久久人妻视频| 色综合天天天天做夜夜| 成人av在线网站| 91碰碰| 天天色天天爱天天爱天天爱y| 婷婷综合视频| 免费看欧美成人A片无码| 五月综亚洲| 成年AAAA色情| 久久精品A片777777| 五月天天爽| 99色干| 丰满人妻妇伦又伦精品国产 | 91久久久久久久91| 最近中文字幕大全免费版在线| 国产精品久久7777777精品无码| 39视频第二区| 婷婷五月天社区| 五月天婷婷丁香社区| 超碰亚洲天堂| 一点色成人网| 欧美日比视频| 国产精品色一哟哟| 亚洲综合婷婷| 热久久婷婷| www.夜夜操.com| 丁香五月天激情婷婷丁香六月 | 欧美婷婷成人| 天天日人人| 99情色五月天| 日本片日本片祼观看网站在线看中文版网页在线看 | av色色国产| 激情婷婷五六月天| 99视频九九热| 国产毛片操B| 五月天婷婷在线AN| 国产成人亚洲综合A∨婷婷| 97丁香五月天| 91九色无码内射| 超碰在线9| 激情网综合| 婷婷五月成年人| 97色啪| 国内自拍97在线| 91一起操| 婷婷五月天激情小说| 99色最新在线视频| 中文资源在线a | 欧美日本国产欧美日本韩国99| 久久AV电影| 99re热| 久热伊人| 大香蕉伊人99| 在线观看亚洲AV| 国产精品VIDEOSSEX久久发布| 久久激情五月婷婷| 天天透天天爱| 婷婷五亚洲| 天天爽在线视频| 婷婷涩涩五月天| 激情骚五月| 五月丁香婷婷狠狠操| 国外亚洲成AV人片在线观看| 天天日日夜夜| 综合色播| 婷婷五月天亚洲| 色播五月网| 丁香六月五月婷婷| 俺去也在线视频| 啪啪啪五月天| 深爱激情九九五月天 | 五月婷婷丁香色播网| 婷婷丁香五月亚洲欧美| 97人人操在线| 9191avse| 91操片| 五月丁香啪啪综合网| 婷婷大乡焦噜噜| 亚洲色图81p| 操日本99| Www.久久| 激情丁香五月综合| 97碰碰人人视频| 超碰色人妾| 五月天另类小说久久小说网| 色欲AVV| 欧美韩国日本| 98国产精品综合一区二区三区| 亚洲亚洲人成综合网络| 五月丁香在线| 精品少妇人妻AV无码专区偷人| 少妇人妻丰满做爰XXX| 欧美精品中文字幕亚洲专区| 五月天开心网| 九九热视频在线观看| 激情五月天婷婷| 大战熟女丰满人妻AV| 中字幕视频在线永久在线观看免费| 亚洲V国产V欧美V久久久久久| 激情内射人妻1区2区3区| 电影91久久久| 精品热九九| 中文字幕综合色| 91丨九色熟女丨首页| 丁香五月AV| 综合激情在线观看| 欧美日本黄色| 丁香五月婷婷无码AV| 色婷婷内射| 青青草六月丁香| 久久久久思思热| 涩婷婷五月天在线精品视频| 五月天另类小说| 99操免费视频| 操骚货在线| 成人做爰A片免费看网站找不到了| 8050一级网| 9视频1在线| 9l视频自拍九色9l视频自拍九色9l社区| 色婷婷狠狠| 五月丁香花伦理电影| 婷婷六月激情综合| 久久五月天综合| 伊人91| 超碰狠狠操| 色香蕉婷婷| 丁香六月婷| av 一区三区四区| 思思久久青草热| 综合网五月天123| 天天爽爽日日做做| 日日干日日| 久久性爱视频| 日本人妻伦在线中文字幕| 婷婷亚洲色| 丁香五月婷婷综合激情啪啪啪| 久久久jd| 激情婷婷五月天网址| 99re这里| 五月婷婷色五月| 北条麻妃伊人| 丁香九月婷| 开心五月婷| 夜夜骑夜夜撸| 五月综合色| 久久婷婷大香蕉| 激情五月色婷婷| 五月丁香综合久久| 色播五月综合网| 99热精品在线| 五月天停停日日| 五月丁香直播| 91婷婷搞| 国产AV成人精品| 大香蕉九九| 久久性爰视频这里只有精品| 香蕉婷婷| 婷婷五月超碰| 色婷操逼| 播四月婷婷六月丁香| 天天干,天天日| 九九热超碰| 中文字幕欧美久久| 天天干天天干天天干天天干天天干天天干天天 | 99日本黄站| 欧美日韩成人综合9| www狠狠| 99色最新在线视频网站| 五月在线| 潮汕成人AV片在线| 色碰碰视频| 少妇达人正片在线播放_ikun_福利吧| 五月丁香婷婷综合| 天堂久久婷婷| 色综合激情| 蜜桃五月天| 伊人久久婷婷| 五月丁香在线| 人人操超碰| 婷婷色无码| 五月天天久久香| 97搞在线| 啪啪91| 婷婷五月激情网| 色天使色综合| 色五月婷婷五月久久| 99精在线| 极品色丁香| 午夜无码精品色综合久久| 99热精品在线| 色色性爱视频| 大香蕉婷婷色| 任你搞网站| 性爱激情五月| 天天免费成年人视频| 噜噜在线| 国产综合丁香五月天| 婷婷丁香五月欧美人| 欧美操人| 99免费成人网| 99热18| 亚洲综合五月天婷婷丁香| 激情五月天激情五月天| 久久久噜噜噜操操操| 欧美日本一区二区三区| 91av传媒高清在线视频网| 全网最新网黄大秀直播高清,主播国产录屏在线| www.五月婷婷| 色五月婷婷av| 久9视频| 日本少妇AA一级特黄大片| 激情亚洲色图片丁香综合| h在线看免费版在线看| 韩日在线熟女| 99热精品在线| 玖玖综合色| 79精品视频在线观看,| 超碰永久在线| 婷婷香五月天| 色色色9 9 9| 久色激情| 成人 AV播放| www.色色色色| 欧美色色色色色色色色| 久久久噜噜噜久久人妻| 五月婷婷色啪| 这里只有精品1| 久热久操久热久草国产91| 9l视频自拍9l九色9l成人| 99久视频| 色开心五月婷婷丁香HD| 婷婷九月丁香| 99久久99视频| 丁香五月影院| 天天拍夜夜撸 | 九月激情婷婷丁香| 婷婷久久欧美| 午夜天堂一区人妻| 国产精品久久久60086| 96丁香婷婷九月蜜桃综合久久| 五月丁香婷婷五月色| 少妇AB又爽又紧无码网站| 丁香婷婷久久老熟女综合网| 久久性刺激| 六月婷婷色色色| 五月天丁香网站| 九九热九九| 丁香婷五月| 色婷婷色综合| 99久在线| 99久久99热| 婷婷大香焦| 色色色色网站| 人妻人人操| 亚洲啪啪啪啪| 亚洲婷婷月丁香五月| 激情小说五月天| eeuus五月婷| 久久成人亚洲欧美电影| 五月综合激情| 五月亭亭六月色| 色婷婷伊人激情在线观看| 亚洲五月天婷婷| 啊v视频在线观看| 天天干 夜夜爽| 六月激情婷婷色| 无码人妻精品一区二区蜜桃色欲| 欧美爆乳一区二区三区| 99大香蕉| 97精品人人A片免费看| 色色综合色| 九九青青草成人| 538在线精品| 情趣视频66| 午夜丁香丁香婷婷| 亚洲欧洲中文日韩久久AV乱码| 激情综合网五月天| 婷婷五月激情热播| 伊人久久大香线蕉亚洲五月天,| 激情五月天偷拍综合网| 五月天色婷伊人| 久久五月情| 久久婷婷色| www,五月丁,com| 丁香五月在线自慰| 91色色五月天| www99精品| 99精品视频免费在线播放| 麻豆忘忧草午夜| 色色网站| 色五月在线播放| 欧美性爱特黄一级aaaassss| 成人毛片在线免费观看| 五月天综合在线网| 在线不卡视频| 久色视频| www.色色色com| 九九激情网| 色播激情五月天| 春色激情第四色| 五月婷啪| 青青草五月天| 日本不卡一区二区三区| 丁香六月在线| 久久久久久综合五月婷婷| 精品国产va久久久久| 99色久| 无码少妇高潮喷水A片免费| 啊V视频在线观看| 天干夜夜操| 久久996re热这里只有精品无码| 任你日视频| 91se视频| 五月婷婷丁香| 久久婷婷网| 五月丁香亚洲综合| 激情五婷精品网在线观看网址| 成人网站av免费网站推荐| 99热爆在线| 天天日天天插| 97色碰| 激情图片婷婷| 婷婷五月天伊人网| 思思精品久久艹| 天天日夜夜高潮| 在线视频另类| www.久久婷婷| 日韩久久日| 国产高清av黄色看片| 丁香六月综合| 四色永久成人网站| 久久最新色| 精品九九视频| 色五月在线| 五月六月播婷婷| 爽极品色| 久久婷婷内射| 成人精品免费在线观看| 国色天香成人网| 天天日天天插| 色五月综合在线| 丁香五月天婷婷激情| 国产婷婷五月天| 色综合五月在线| 成人婷婷色五月天| www.粉嫩av.com| 五月丁香六月色婷| 色噜噜婷婷| 日本人妻A片成人免费看片| 久久香蕉福利| 991自拍视频| 99草在线免费观看视频| 97碰碰免费.视频| 激情5月婷婷| 日韩二区搞逼插逼毛片| 久在线88综合| 成人.在线日韩| 五月婷婷六月天| 五月丁香啪啪网| 五月丁香综合网| 婷婷五月天av| 色五月综合| 国自产拍偷拍精品啪啪一区二区| 五月婷婷基地| 色五月婷婷五月天| 熟女人妻一区二区三区免费看| 成人无码髙潮喷水A片| 国精产品一区一区三区免费视频| www.婷婷.com| 99在线精品观看99| 嫩BBB搡BBBB榛BBBB| AV大片在线播放| 免費观看aV在线网址| 嫩草视频。| 99热99| AV网在线观看| www,超碰| 久久综合五月天| a在线观看| 另类色视频| 99精品在| 五月深爱网| 丁香五月最新地址| 婷五月天丁香婷五月| 五月天婷婷基地综合网| 久久婷婷视频| 无码毛片992367| 五月天婷亚洲天综合网综合| 美女主播野战视步页| 色五月丁香伊人五月| 开心婷婷五月| 色婷婷五月综合| 精品国产乱码久久久久夜深人妻| 婷婷色网址| 五月婷婷婷综合网| 国产伊人五月天| 丁香五月六月激情| 人人人舔人人人操人人人摸人人人97| 色五月婷婷一二| 97 A I色色| 欧美日韩999| 婷婷丁香久久网| 亚洲午夜电影| 欧美在线骚货| 丁香五月激情综合啪啪| 国产三级片91| 人妻久久久久久| 无码激情AAAAA片-区区| 伊人久热91| 天天曰夜夜爽| 婷婷丁香五月天欧美| 丁香六月婷婷高清| 天天操夜夜肏| 色噜噜五月天| 极品人妻XXXXOOOO| 九月丁香网婷婷| 天天日夜夜欢| 色综合五月婷婷狠狠干| 丁香婷婷五月基地| 97九色| 99丁香五月| 久久182| 色色丁香| 26uuu国产激情视频| 99操碰| 91精选国| 成人日韩欧美| 九九视频在线观看| 96精品成人无码A片观看金桔| 亚洲婷婷激情综合激情999精品| 激情综合网激情五月欧美| 色丁香婷婷美女视频网站| 玖玖无码中文| 五月激香蕉网| 天天操天天日天天爱| 五月婷婷六月丁香在线| 亚洲中文字幕av| 色婷婷AⅤ| 五月色婷婷影视在线电影| 五月婷激情影院| 热日韩欧美| 7月婷婷六月丁香| 五月天婷婷7米| 国产精品99久久久久久久女警| 色噜噜狠狠色综合成人99| 久久这里有精品视频| 天天日日夜夜| 久久婷婷啪啪视频| 几激情五月婷婷色五月色天堂| 色狠狠色噜噜AV天堂五区| 综合色色婷婷| www.国产色| 丁香五月婷婷啪啪视频| 国产99美少妇| 婷婷色五月激情强奸四射| 丁香五月激情啪啪啪| 26uu| 丁香五月偷拍| 99久在线视频| 99看片| 欧美日韩国产一二区| 欧美天天性| 色爱综合网| 久久这里只有精品久久| 九月综合| www.com任你艹| 日日夜夜爽| 99se丁香| 天天爱天天做天天舔| 99热网站| 久久色五月| 丁香六月综合激情| 99综合成人视频在线观看| 久久五月网| 日日日日日| 五月婷婷六月丁香激情深爱| 久久3p| 97色永久免费视频| 九九色色| 免费AV在线网址| 色婷婷视频在线| 无码色| 99热这是里只有精品| 99热日本| 亚洲日韩国产黑丝黑丝AVAV一区二区三区| 丁香五月婷婷AV| 欧美色宗和激情| 五月丁香在线| 色吊丝永久访问网址| 五月婷婷色播| 99色在线观看视频| 婷婷五月丁香色综合| 日韩成人电影在线播放| 五月天婷婷色色网| 九九九色综合| 任我肏| 91视频一起草| 中文无码婷婷| 亚洲a色| 婷婷开心深爱五月天| 天天天天操| 天天干-天天日| 三级片AAA久久久AAA久久久AAA| 草婷婷在线| #NAME?| 亚洲婷婷激情五月天| 亚洲在线成人| 熟女网站久久| 亚洲免费观看高清完整版AV线| 欧美日本黄色| 99九九视频| 26UUU欧美| 丁香五月瑟瑟| 97天堂| 五月伊人视频在线看| 婷婷五月花.97| 五月婷婷m| 97碰碰草| 五月婷婷免费在线视频| 外国碰视频网站97| 99这里都是精品6| 就爱啪啪婷婷| 波多野结衣成人作品在线| 五月天亭亭俺也| 9 1超碰九色| 99国产精品白浆在线观看免费| 亚洲看av的网站| 激情国产五月| 久久黄色片| tingtingseav| 综合伊人久久| 欧美久久婷婷| 久久激情五月| www.夜夜.com| 在线视频激情网站| 婷婷综合网| 久久96热| 五月亭亭欧美女人| 天天色色天天| 五月综合激情视频| 日本九九网| 日日综合网| 爱婷婷五月| 伊人色综合影院视频| 狠狠色婷婷7777久| 天天综合网网欲色| 婷婷丁香97| 国产精自产拍久久久久久蜜 | 婷婷五月天综合色| 五月丁香自拍| 亚洲精品久久久无码| 51avj视频大全| 无码se| 亚洲AV久久久久久久久久久久久久久久| 色综合五月婷婷狠狠干| 碰碰人人漕| 国产毛多水多女人A片| 99视频在线精品| 亚洲性受XXXX五月丁香| 婷婷丁香五月天操逼| www.色五月| 99热在线这里|