vuepress打包部署踩坑及解決
vuepress打包部署踩坑記錄
官網(wǎng)給了多種部署方案,這里我才用的是部署到github上
在你的項目中,創(chuàng)建一個如下的 deploy.sh 文件(請自行判斷去掉高亮行的注釋):
#!/usr/bin/env sh # 確保腳本拋出遇到的錯誤 set -e # 生成靜態(tài)文件 npm run docs:build # 進入生成的文件夾 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> /**這個地方換成自己的github地址和倉庫地址**/ git push -f git@github.com:FightingN/vue-common-vuepress.git master:gh-pages cd -
然后需要注意的是 .vuepress/config.js文件的base需要修改一下
base: '/vue-common-vuepress/',
然后運行npm run deploy就可以正常打包到github托管中了
vuepress打包報錯:error Error rendering /:
問題
使用vuepress寫文檔網(wǎng)站,為了實現(xiàn)element-ui類似的組件預覽效果,項目里面將ant-design-vue和基于ant-design-vue的自己封裝的組件引入項目中,開發(fā)環(huán)境能正常運行。當運行Build打包后,報錯:error Error rendering /:
方案1
經(jīng)查詢vuepress github issuse 得到的答案是,vuepress是服務端渲染的,瀏覽器的 API 訪問限制。在頁面加載第三方組件的時候,可能出現(xiàn)找不到的情況,建議在當前頁面使用時再引入。
當然,如果不需要組件預覽效果,及:::demo標志,就不會報錯。需要該效果時,按照官網(wǎng)的做法,使用component標簽,在需要的md 代碼塊里面動態(tài)加載組件,可以解決該問題
mounted(){ import("my-component").then(myComponent=>{ console.log("myComponent", myComponent) this.dynamicComponent = myComponent.Tree }) },
當然還有一種方法就是在mounted里面import組件并且注冊組件,template部分照常使用之前的標簽
<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>
然而運行后,報錯my-tree沒有注冊。
Unknown custom element: - did you register the component correctly? For recursive components, make sure to provide the “name” option.
found in
方案2
方案1,問題看是解決了,沒有報錯了,但是。這不是我們想要的。
本質需求是實現(xiàn)組件庫的組件預覽效果,并且能復制代碼,方案1能預覽,但是代碼都變成了component標簽,不符合需求。
接下來我們想排查下是什么組件影響了打包:
采用本地建測試倉庫,本地建測試組件庫,本地建測試文檔項目,逐個移植原組件庫的組件到測試組件庫中,發(fā)布到測試倉庫后,更新測試文檔,然后執(zhí)行本地預覽和打包命令。最終找出影響打包的組件有dialog,uploadAvatar,preview,cropper-img等組件。這些組件的共同點就是都直接或間接用到了document操作dom,還有其他window的方法,或者bom的方法事件,或者在組件內(nèi)注冊第三方組件,如本項目中就用的atob,btoa,這個也是造成出現(xiàn)該錯誤的原因之一。經(jīng)在upoadAvatar去掉document得到驗證。目前除了這幾個組件,其他均可以實現(xiàn)組件預覽效果。但是這幾個組件只要引入就報錯,也影響了全局。
最終解決
知道了問題所在,結合上面的思路,總之的一點就是想要用window或bom方法事件,一定要在mounted后執(zhí)行。這里來一個一個看。首先看dialog組件,之所以會報錯就是dialog組件在created生命周期的時候用了document(下面只展示關鍵代碼,多余的代碼略)
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 { ... } }
那這里就很簡單,將created改成mounted就行
再來看看圖片裁剪組件,之前的代碼是
<!--圖片裁剪--> <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組件的按需引入問題。按照vue-press的思路,可以使用動態(tài)import,于是開始嘗試如下:
<!--圖片裁剪--> <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>
然而運行后發(fā)現(xiàn),沒有生效。于是將import(“vue-cropper”).catch打印發(fā)現(xiàn)竟然報錯了。vuepress是走node服務渲染模式,也可能和nodejs 服務端渲染不支持import有關,于是改成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>
結果成功,引入該組件后,也不會再報錯error Error rendering /:
然后看看頭像上傳組件,這個也比較坑。這個組件mounted沒有document,也沒引入第三方組件。無奈,只有使用注釋大法逐步查找,最后確定是組件內(nèi)部引入壓縮圖片的方法造成
import { compressImageFun } from "../../utils/img-method"
發(fā)現(xiàn)只要組件引入了該方法,不管是否使用,都會報錯,而注釋該方法就萬事大吉。
于是取查找compressImageFun相關,開始因為無頭緒,同樣只能使用注釋大法,最后查到罪魁禍首是atob,btoa函數(shù)。這樣那么解決辦法和引入第三方組件類似。compressImageFun里面不需要動,改引入的地方就行,如下
export default { name: "UploadAvatar", data () { return { compressImageFun: null, // 壓縮函數(shù) 注意這里因為無法直接使用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 } ... }) }, }
至此,該錯誤被攻克?。?!
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
vuex結合session存儲數(shù)據(jù)解決頁面刷新數(shù)據(jù)丟失問題
在項目中表單篩選項里,選擇完之后刷新頁面數(shù)據(jù)就變了,沒有保留在自己選擇的選項上。本文使用session存儲數(shù)據(jù),具有一定的參考價值,感興趣的可以了解一下2021-09-09vue開發(fā)chrome插件,實現(xiàn)獲取界面數(shù)據(jù)和保存到數(shù)據(jù)庫功能
這篇文章主要介紹了vue開發(fā)chrome插件,實現(xiàn)獲取界面數(shù)據(jù)和保存到數(shù)據(jù)庫功能的示例,幫助大家更好的理解和使用vue,感興趣的朋友可以了解下2020-12-12Element UI 上傳組件實現(xiàn)文件上傳并附帶額外參數(shù)功能
在使用 ElementUI 的上傳組件 el-upload 實現(xiàn)文件上傳功能時,如果單文件上傳是比較簡單的,但是在實際需求中,往往會在上傳文件時伴隨著一些其他參數(shù),怎么操作呢,下面通過示例代碼講解感興趣的朋友一起看看吧2023-08-08vue.js利用defineProperty實現(xiàn)數(shù)據(jù)的雙向綁定
本篇文章主要介紹了用Node.js當作后臺、jQuery寫前臺AJAX代碼實現(xiàn)用戶登錄和注冊的功能的相關知識。具有很好的參考價值。下面跟著小編一起來看下吧2017-04-04