vuepress打包部署踩坑及解決
vuepress打包部署踩坑記錄
官網(wǎng)給了多種部署方案,這里我才用的是部署到github上
在你的項(xiàng)目中,創(chuàng)建一個(gè)如下的 deploy.sh 文件(請(qǐng)自行判斷去掉高亮行的注釋?zhuān)?
#!/usr/bin/env sh # 確保腳本拋出遇到的錯(cuò)誤 set -e # 生成靜態(tài)文件 npm run docs:build # 進(jìn)入生成的文件夾 cd docs/.vuepress/dist # 如果是發(fā)布到自定義域名 # echo 'www.example.com' > CNAME git init git add -A git commit -m 'deploy' # 如果發(fā)布到 https://<USERNAME>.github.io # git push -f git@github.com:<USERNAME>/<USERNAME>.github.io.git main # 如果發(fā)布到 https://<USERNAME>.github.io/<REPO> /**這個(gè)地方換成自己的github地址和倉(cāng)庫(kù)地址**/ git push -f git@github.com:FightingN/vue-common-vuepress.git master:gh-pages cd -
然后需要注意的是 .vuepress/config.js文件的base需要修改一下
base: '/vue-common-vuepress/',
然后運(yùn)行npm run deploy就可以正常打包到github托管中了
vuepress打包報(bào)錯(cuò):error Error rendering /:
問(wèn)題
使用vuepress寫(xiě)文檔網(wǎng)站,為了實(shí)現(xiàn)element-ui類(lèi)似的組件預(yù)覽效果,項(xiàng)目里面將ant-design-vue和基于ant-design-vue的自己封裝的組件引入項(xiàng)目中,開(kāi)發(fā)環(huán)境能正常運(yùn)行。當(dāng)運(yùn)行Build打包后,報(bào)錯(cuò):error Error rendering /:
方案1
經(jīng)查詢(xún)vuepress github issuse 得到的答案是,vuepress是服務(wù)端渲染的,瀏覽器的 API 訪問(wèn)限制。在頁(yè)面加載第三方組件的時(shí)候,可能出現(xiàn)找不到的情況,建議在當(dāng)前頁(yè)面使用時(shí)再引入。
當(dāng)然,如果不需要組件預(yù)覽效果,及:::demo標(biāo)志,就不會(huì)報(bào)錯(cuò)。需要該效果時(shí),按照官網(wǎng)的做法,使用component標(biāo)簽,在需要的md 代碼塊里面動(dòng)態(tài)加載組件,可以解決該問(wèn)題
mounted(){ import("my-component").then(myComponent=>{ console.log("myComponent", myComponent) this.dynamicComponent = myComponent.Tree }) },
當(dāng)然還有一種方法就是在mounted里面import組件并且注冊(cè)組件,template部分照常使用之前的標(biāo)簽
<template> <my-tree/> </template> <script> import Vue from "vue" export default { mounted(){ import("my-component").then(myComponent=>{ console.log("myComponent", myComponent) Vue.component("myTree",myComponent.Tree) }) } } </script>
然而運(yùn)行后,報(bào)錯(cuò)my-tree沒(méi)有注冊(cè)。
Unknown custom element: - did you register the component correctly? For recursive components, make sure to provide the “name” option.
found in
方案2
方案1,問(wèn)題看是解決了,沒(méi)有報(bào)錯(cuò)了,但是。這不是我們想要的。
本質(zhì)需求是實(shí)現(xiàn)組件庫(kù)的組件預(yù)覽效果,并且能復(fù)制代碼,方案1能預(yù)覽,但是代碼都變成了component標(biāo)簽,不符合需求。
接下來(lái)我們想排查下是什么組件影響了打包:
采用本地建測(cè)試倉(cāng)庫(kù),本地建測(cè)試組件庫(kù),本地建測(cè)試文檔項(xiàng)目,逐個(gè)移植原組件庫(kù)的組件到測(cè)試組件庫(kù)中,發(fā)布到測(cè)試倉(cāng)庫(kù)后,更新測(cè)試文檔,然后執(zhí)行本地預(yù)覽和打包命令。最終找出影響打包的組件有dialog,uploadAvatar,preview,cropper-img等組件。這些組件的共同點(diǎn)就是都直接或間接用到了document操作dom,還有其他window的方法,或者bom的方法事件,或者在組件內(nèi)注冊(cè)第三方組件,如本項(xiàng)目中就用的atob,btoa,這個(gè)也是造成出現(xiàn)該錯(cuò)誤的原因之一。經(jīng)在upoadAvatar去掉document得到驗(yàn)證。目前除了這幾個(gè)組件,其他均可以實(shí)現(xiàn)組件預(yù)覽效果。但是這幾個(gè)組件只要引入就報(bào)錯(cuò),也影響了全局。
最終解決
知道了問(wèn)題所在,結(jié)合上面的思路,總之的一點(diǎn)就是想要用window或bom方法事件,一定要在mounted后執(zhí)行。這里來(lái)一個(gè)一個(gè)看。首先看dialog組件,之所以會(huì)報(bào)錯(cuò)就是dialog組件在created生命周期的時(shí)候用了document(下面只展示關(guān)鍵代碼,多余的代碼略)
import { VNode } from "vue" import { Component, Prop, Vue, Watch } from "vue-property-decorator" import { dialogConfig } from "./type" export default class Dialog extends Vue { created() { this.dialogInit() this.getWindowSize() } /** * 彈窗初始化 * @private */ private dialogInit():void { this.id = "lc-dialog" + (Math.random() * 1000000 + new Date().getTime()).toString(16).split(".")[0] this.$nextTick(() => { const dialogDom:any = document.getElementById(that.id) if (!dialogDom) { return } this.dialogDom = dialogDom this.headerDom = dialogDom.querySelector(".ant-modal-header") this.footerDom = dialogDom.querySelector(".ant-modal-footer") }) } /** * 獲取窗口尺寸 * @private */ private getWindowSize():void { const that = this as any this.windowSize = { windowWidth: document.documentElement.clientWidth, windowHeight: document.documentElement.clientHeight } // // console.log(that.dialogScreen) // // console.log(that.isScreen) window.onresize = () => { if (this.dialogScreen && this.isScreen) { clearTimeout(this.debounceTimeOut) this.debounceTimeOut = setTimeout(() => { this.windowSize = { windowWidth: document.documentElement.clientWidth, windowHeight: document.documentElement.clientHeight } }, 300) } } } render (h:any):VNode { ... } }
那這里就很簡(jiǎn)單,將created改成mounted就行
再來(lái)看看圖片裁剪組件,之前的代碼是
<!--圖片裁剪--> <template> <lc-dialog :title="title" :visible.sync="visible" :width="800" :footer="null" ref="cropperModal" :before-close="beforeClose" :z-index="zIndex" > <vue-cropper ref="cropper" :img="img" :info="true" :auto-crop="options.autoCrop" :output-type="config.outputType || (config.originFile ? config.originFile.type : '')" :auto-crop-width="options.autoCropWidth" :auto-crop-height="options.autoCropHeight" :fixed-box="options.fixedBox" @real-time="realTime" > </vue-cropper> </lc-dialog> </template> <script> import Vue from "vue" import VueCropper from "vue-cropper" import { getZIndexByDiv } from "../../utils/lc-methods" Vue.use(VueCropper) export default { name: "CropperImg", ... } </script>
這里需要解決的是vue-cropper組件的按需引入問(wèn)題。按照vue-press的思路,可以使用動(dòng)態(tài)import,于是開(kāi)始嘗試如下:
<!--圖片裁剪--> <template> <lc-dialog :title="title" :visible.sync="visible" :width="800" :footer="null" ref="cropperModal" :before-close="beforeClose" :z-index="zIndex" > <component v-if="component" :is="component" ref="cropper" :img="img" :info="true" :auto-crop="options.autoCrop" :output-type="config.outputType || (config.originFile ? config.originFile.type : '')" :auto-crop-width="options.autoCropWidth" :auto-crop-height="options.autoCropHeight" :fixed-box="options.fixedBox" @real-time="realTime" /> </lc-dialog> </template> <script> import { getZIndexByDiv } from "../../utils/lc-methods" export default { name: "CropperImg", mounted() { import("vue-cropper").then(VueCropperModule => { this.component = VueCropperModule.VueCropper } }, ... } </script>
然而運(yùn)行后發(fā)現(xiàn),沒(méi)有生效。于是將import(“vue-cropper”).catch打印發(fā)現(xiàn)竟然報(bào)錯(cuò)了。vuepress是走node服務(wù)渲染模式,也可能和nodejs 服務(wù)端渲染不支持import有關(guān),于是改成require引入,如下
<!--圖片裁剪--> <template> <lc-dialog :title="title" :visible.sync="visible" :width="800" :footer="null" ref="cropperModal" :before-close="beforeClose" :z-index="zIndex" > <component v-if="component" :is="component" ref="cropper" :img="img" :info="true" :auto-crop="options.autoCrop" :output-type="config.outputType || (config.originFile ? config.originFile.type : '')" :auto-crop-width="options.autoCropWidth" :auto-crop-height="options.autoCropHeight" :fixed-box="options.fixedBox" @real-time="realTime" /> </lc-dialog> </template> <script> import { getZIndexByDiv } from "../../utils/lc-methods" export default { name: "CropperImg", mounted() { const VueCropperModule = require("vue-cropper") // console.log("VueCropperModule", VueCropperModule) this.component = VueCropperModule.VueCropper }, ... } </script>
結(jié)果成功,引入該組件后,也不會(huì)再報(bào)錯(cuò)error Error rendering /:
然后看看頭像上傳組件,這個(gè)也比較坑。這個(gè)組件mounted沒(méi)有document,也沒(méi)引入第三方組件。無(wú)奈,只有使用注釋大法逐步查找,最后確定是組件內(nèi)部引入壓縮圖片的方法造成
import { compressImageFun } from "../../utils/img-method"
發(fā)現(xiàn)只要組件引入了該方法,不管是否使用,都會(huì)報(bào)錯(cuò),而注釋該方法就萬(wàn)事大吉。
于是取查找compressImageFun相關(guān),開(kāi)始因?yàn)闊o(wú)頭緒,同樣只能使用注釋大法,最后查到罪魁禍?zhǔn)资莂tob,btoa函數(shù)。這樣那么解決辦法和引入第三方組件類(lèi)似。compressImageFun里面不需要?jiǎng)樱囊氲牡胤骄托?,如?/p>
export default { name: "UploadAvatar", data () { return { compressImageFun: null, // 壓縮函數(shù) 注意這里因?yàn)闊o(wú)法直接使用compressImageFun,所以需要存在data中使用 } }, mounted() { const imgMethod = require("../../utils/img-method") this.compressImageFun = imgMethod.compressImageFun }, methods: { /** * 上傳之前 * @param file * @returns {boolean} */ async beforeUpload (file) { return new Promise(async (resolve, reject) => { ...省略若干代碼 if (!this.noCompress) { newCompressFile = await this.compressImageFun({ file: cropperFile || file }) cropperFile = newCompressFile.data } ... }) }, }
至此,該錯(cuò)誤被攻克?。?!
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
vuex結(jié)合session存儲(chǔ)數(shù)據(jù)解決頁(yè)面刷新數(shù)據(jù)丟失問(wèn)題
在項(xiàng)目中表單篩選項(xiàng)里,選擇完之后刷新頁(yè)面數(shù)據(jù)就變了,沒(méi)有保留在自己選擇的選項(xiàng)上。本文使用session存儲(chǔ)數(shù)據(jù),具有一定的參考價(jià)值,感興趣的可以了解一下2021-09-09vue開(kāi)發(fā)chrome插件,實(shí)現(xiàn)獲取界面數(shù)據(jù)和保存到數(shù)據(jù)庫(kù)功能
這篇文章主要介紹了vue開(kāi)發(fā)chrome插件,實(shí)現(xiàn)獲取界面數(shù)據(jù)和保存到數(shù)據(jù)庫(kù)功能的示例,幫助大家更好的理解和使用vue,感興趣的朋友可以了解下2020-12-12Element UI 上傳組件實(shí)現(xiàn)文件上傳并附帶額外參數(shù)功能
在使用 ElementUI 的上傳組件 el-upload 實(shí)現(xiàn)文件上傳功能時(shí),如果單文件上傳是比較簡(jiǎn)單的,但是在實(shí)際需求中,往往會(huì)在上傳文件時(shí)伴隨著一些其他參數(shù),怎么操作呢,下面通過(guò)示例代碼講解感興趣的朋友一起看看吧2023-08-08vue3修改link標(biāo)簽?zāi)J(rèn)icon無(wú)效問(wèn)題詳解
這篇文章主要介紹了vue3修改link標(biāo)簽?zāi)J(rèn)icon無(wú)效問(wèn)題詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10vue2.0路由切換后頁(yè)面滾動(dòng)位置不變BUG的解決方法
下面小編就為大家分享一篇vue2.0路由切換后頁(yè)面滾動(dòng)位置不變BUG的解決方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-03-03vue.js利用defineProperty實(shí)現(xiàn)數(shù)據(jù)的雙向綁定
本篇文章主要介紹了用Node.js當(dāng)作后臺(tái)、jQuery寫(xiě)前臺(tái)AJAX代碼實(shí)現(xiàn)用戶(hù)登錄和注冊(cè)的功能的相關(guān)知識(shí)。具有很好的參考價(jià)值。下面跟著小編一起來(lái)看下吧2017-04-04