概述
在用nuxt開發服務端渲染項目並引入第三方庫的時候,經常會遇到window或document未定義的情況,原因是這個第三方庫里面用到了window或者document,然后在服務端打包的時候,node環境並沒有window或者document,所以就報了window或document未定義的錯誤。
而且,我們在引入第三方庫的時候,並不希望把第三方庫打包進app.js,而是希望這個第三方庫只在需要的頁面才加載。
下面以tinymce這個第三方庫為例,記錄我在nuxt.js框架中的實現方法,供以后開發時參考,相信對其他人也有用。
官網方法
我們不能把tinymce放到plugin里面去引入,因為這樣會引入到全局js里面去。
nuxt官網介紹了一種方法:Window 或 Document 對象未定義?,但是寫的很簡略,我這里詳細說明一下。
首先我們在要引入的blog.vue文件中,通過判斷是否是客戶端來選擇性的加載tinymce這個庫:
let tinymce;
if (process.client) {
tinymce = require('tinymce/tinymce');
// A theme is also required
require('tinymce/themes/silver/theme');
// Any plugins you want to use has to be imported
require('tinymce/plugins/advlist');
require('tinymce/plugins/wordcount');
require('tinymce/plugins/autolink');
require('tinymce/plugins/autosave');
require('tinymce/plugins/charmap');
require('tinymce/plugins/codesample');
require('tinymce/plugins/contextmenu');
require('tinymce/plugins/emoticons');
require('tinymce/plugins/fullscreen');
require('tinymce/plugins/hr');
require('tinymce/plugins/imagetools');
require('tinymce/plugins/insertdatetime');
require('tinymce/plugins/link');
require('tinymce/plugins/media');
require('tinymce/plugins/noneditable');
require('tinymce/plugins/paste');
require('tinymce/plugins/print');
require('tinymce/plugins/searchreplace');
require('tinymce/plugins/tabfocus');
require('tinymce/plugins/template');
require('tinymce/plugins/textpattern');
require('tinymce/plugins/visualblocks');
require('tinymce/plugins/anchor');
require('tinymce/plugins/autoresize');
require('tinymce/plugins/bbcode');
require('tinymce/plugins/code');
require('tinymce/plugins/colorpicker');
require('tinymce/plugins/directionality');
require('tinymce/plugins/fullpage');
require('tinymce/plugins/help');
require('tinymce/plugins/image');
require('tinymce/plugins/importcss');
require('tinymce/plugins/legacyoutput');
require('tinymce/plugins/lists');
require('tinymce/plugins/nonbreaking');
require('tinymce/plugins/pagebreak');
require('tinymce/plugins/preview');
require('tinymce/plugins/save');
require('tinymce/plugins/spellchecker');
require('tinymce/plugins/table');
require('tinymce/plugins/textcolor');
require('tinymce/plugins/toc');
require('tinymce/plugins/visualchars');
require('tinymce/skins/lightgray/skin.min.css';
}
這樣,在服務端就不會引入這些庫,只會在客戶端引入。但是服務端沒有引入的話,相關js在執行的時候會報不存在的錯誤,這里就需要再用process.client判斷一下環境再執行。示例如下:
if (process.client) {
tinymce.init({
...options,
...this.otherOptions,
language: this.language,
});
)
script方法
有時候我們希望用引入tinymce.js的方法來引入,而不用webpack打包的方式。這個時候我們需要在blog.vue里面加上如下代碼即可:
export default {
name: 'Blog',
layout: 'blank',
head: {
script: [
{ src: '/tinymce.5.0.4/tinymce.min.js' },
],
},
}
其中上面src的路徑是static文件夾的絕對路徑。
按照上述的方法會有一個問題,就是執行下面的代碼的時候,即使用了process.client,但還是會報tinymce不存在的錯誤:
if (process.client) {
tinymce.init({
...options,
...this.otherOptions,
language: this.language,
});
)
原因是,客戶端打包的時候,tinymce確實是沒有定義的。所以這里改成如下形式即可:
if (process.client) {
window.tinymce.init({
...options,
...this.otherOptions,
language: this.language,
});
)
其它
nuxt有一個組件是no-ssr組件,所以上面的html最好用no-ssr包起來,不然會報tinymce組件沒有定義的錯誤:
<no-ssr placeholder="Loading...">
<tinymce
id="myTinymce"
v-model="content"
:height="600"
/>
</no-ssr>