不會 webpack 還想學 vue 工程化開發 的福音
熟悉jQuery開發的,學習vue的簡單使用是沒用啥問題的,但是學習vue的工程化開發方式,往往會遇到各種問題,比如:
webpack、node、npm、cnpm、yarn、腳手架、開發環境、測試環境、生產環境、各種安裝、各種創建。
好在 vue3 不容易報錯了,想當初 vue2.x 的時候各種報錯,看到錯誤就只能干瞪眼,這都是啥?好像是webpack的報錯。
當初學 vue2 就卡在了建立項目上,各種嘗試居然一個項目都沒跑起來。
如果能像jQuery那樣,直接開魯那多好呀!
各種陰差陽錯+機緣巧合的情況下,弄出來了這種在 CND 模式下仿工程化開發的方式。一開始只是想方便我做在線演示,后來各種完善,發現還是應該有點搞頭了。再加上大神在弄vite,似乎也是對webpack比較頭疼。。。
好了不墨跡了,開始說我的做法。
vue全家桶和UI庫的加載方式
這個很傳統了,官方也支持。
<script src="https://unpkg.com/vue@3.0.5/dist/vue.global.js"></script>
<script src="https://unpkg.com/vue-router@4.0.3/dist/vue-router.global.js"></script>
<script src="https://unpkg.com/vuex@4.0.0-rc.2/dist/vuex.global.js"></script>
<link href="https://unpkg.com/element-plus@1.0.2-beta.30/lib/theme-chalk/index.css" rel="stylesheet">
<script src="https://unpkg.com/element-plus@1.0.2-beta.30/lib/index.full.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
瀏覽器會對js文件做緩存,第一次有點慢,后緩存后就快了。
某網站有時候會卡一下,不卡的話還是很快的。
js代碼的加載方式
<script type="module" src="src/main.js?v=4"></script>
聽說vite也是這么加載的。好吧就是從vite建立的項目里copy來的。
要加上 type="module" 否則加載不了。
文件夾結構和代碼編寫風格
文件夾當然是把工程化的拿過來之間用了,挺簡潔明了的。
因為瀏覽器也支持 import 的方式加載js,那么也就是說,CDN方式下也可以用import加載。那么js代碼方面也不會有太大的差別。
我們來對比一下:
左面是CND的項目,右面是工程化的項目。
- 文件夾結構完全一致,
- js文件都能對應上
- vue文件拆分成 html + js 兩個文件(app.vue除外)
main.js
/*
import store from './store/index.js?v=1'
import router from './router/index.js?v=1'
import App from './app.js?v=1'
// 創建vue3的實例
const app = Vue.createApp(App)
.use(store)
.use(router)
.use(ElementPlus)
.mount('#app')
*/
const ver = window.__ver || ''
Promise.all([
import('./store/index.js' + ver),
import('./router/index.js' + ver),
import('./app.js' + ver),
]).then((res) => {
// 創建vue3的實例
const app = Vue.createApp(res[2].default)
.use(res[0].default) // 掛載vuex
.use(res[1].default) // 掛載路由
.use(ElementPlus) // 加載ElementPlus
.mount('#app') // 掛載Vue的app實例
})
注釋掉的代碼,和工程化里的代碼是一致的,只是這種方式只支持常量,所以想把版本加在url地址上面就比較麻煩。
所以改為了這種異步的方式,這樣可以把版本號給拼接上去。這樣更新瀏覽器的js緩存就方便多了。
app.js
export default {
name: 'app',
setup() {
do something...
return {
}
}
}
工程化項目里面是App.vue,對應的是網頁里 id=“app” 的div。
這里改成純js文件的形式,因為模板就是index.html的div。
好吧,其實是main.js里面的加載方式不知道要怎么改。。。
router
const routes = [
{
path: '/',
name: 'Home',
component: () => myImport('views/home')
},
{
path: '/About',
name: 'About',
component: () => myImport('views/About')
},
{
path: '/component',
name: 'component',
component: () => myImport('views/component')
},
{
path: '/store',
name: 'store',
component: () => myImport('views/store')
}
]
const router = VueRouter.createRouter({
history: VueRouter.createWebHistory(),
routes
})
export default router
-
動態路由
這里采用動態路由的方式,另外換成了我自己封裝的函數,可以加載html和js文件,然后變成動態組件的方式,這樣組件就可以被路由加載了。 -
路徑設置問題
本來想把html和js文件放在一個文件夾里面,就可以用同一個url加載了,結果和我想的不一樣。
由於加載 html 和加載 js 的路徑規則不太一樣,再加上路由導航的原因,
所以只好用 src 作為分隔標識,統一從src開始計算路徑。
myImport
// 直接放在Window里面好了。。。
window.myImport = (url) => {
return new Promise((resolve, reject) => {
const ver = window.__ver || ''
const baseUrl = window.__basrUrl || '/src/'
// 先加載js
import(baseUrl + url + '.js' + ver).then((resjs) => {
const js = resjs.default
if (js.template === '') {
// 如果模板是空的,表示需要加載html作為模板
axios.get(baseUrl + url + '.html' + ver).then((resHTML) => {
js.template = resHTML.data
resolve(js)
})
} else {
// 否則直接使用js注冊組件
resolve(js)
}
})
})
}
一開始還想做個插件掛到vue上面,后來試了半天沒成功。
然后覺得自己挺傻的,cnd環境,一個靜態函數,直接掛在Window上面不就行了嗎。
-
加載 js 和 html
先用 import 異步加載 js,目的是便於拼接url,然后判斷是否有template。
如果有的話,就不加載html了。
如果沒有的話,在用axios加載html,然后設置給template,這樣就變成了一個標准的js組件。 -
是否會重復加載?
組件自帶緩存機制,第一次會加載,以后就不會重復加載了。
store
import { Set_Count } from './mutation-types.js'
export default Vuex.createStore({
state: {
count: 0,
myObject: {
time: '現在的時間:'
},
myArray: [1,2,2,3,4]
},
getters: {
getAddCount: (state) => {
return state.count + 1
}
},
mutations: {
// 計數器
setCount(state, num = 1) {
state.count += num
},
[Set_Count](state, num = 1) {
state.count += num
}
},
actions: {
},
modules: {
}
})
基本上沒啥區別。
如何方便的寫模板
直接看圖,更清晰一些。
一邊寫js代碼,另一邊寫模板。這樣也是很方便的。
一開始想在瀏覽器里面直接加載vue文件,然后處理成js組件。
想了半天,理論上應該可以,但是我這水平估計夠嗆,所以采用了這種折中的方式。
組件里面加載組件
- defineAsyncComponent
這個是Vue提供的異步組件,如果在工程化里面,可以直接加載vue文件。
我在cnd里面試了一下,沒成功。所以只好用純js組件的方式。
動態路由不需要套這個,但是異步組件就要套上,否則沒有效果。
搭一個梯子
這樣做項目和 jQuery 的風格挺像的,文件copy過來,建立個網站就可以開魯了。
同時代碼編寫方式又采用工程化的方式,熟悉之后可以方便的切換的工程化的開發方式。
就好像在 jQuery 與 vue 的工程化直接搭了一個梯子,應該大概可以方便我們翻過去吧。
便於調試
-
設置斷點看狀態。
-
看成員
-
進到內部了,好吧其實我都看不懂。。。
js文件的緩存問題
緩存是個好東東,避免我們重復加載js文件,加快頁面顯示速度,但是如果我們的js改了,瀏覽器卻還是在用緩存怎么辦?
我們可以設置一個版本號,加載文件后面就可以。當更新的時候,改一下版本號,就可以重新加載了。
源碼
https://github.com/naturefwvue/nf-vue-cnd/tree/main/cnd/project-template
在線演示
https://naturefwvue.github.io/nf-vue-cnd/cnd/project-template/
一開始可能會有的卡,第一次點導航會加載文件,所以會慢一點,以后就好了。好像應該加一個加載中的狀態。