Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
ue作為三大主流前端開發(fā)框架之一,近年來用戶群發(fā)展迅速,用其開發(fā)的軟件項(xiàng)目越來越多。
vue開發(fā)環(huán)境(development)和生產(chǎn)環(huán)境(production)的構(gòu)建目標(biāo)差異很大。
開發(fā)環(huán)境中,我們需要具有強(qiáng)大的,具有實(shí)時(shí)重新加載(live reloading)或熱模塊替換(hot module replacement)能力的 source map 和 localhost server。
生產(chǎn)環(huán)境中,我們的目標(biāo)則轉(zhuǎn)向于關(guān)注更小的 bundle,更輕量的 source map,以及更優(yōu)化的資源,以改善加載時(shí)間。
遵循邏輯分離原則,通常為每個(gè)環(huán)境編寫彼此獨(dú)立的 webpack 配置。同時(shí)遵循不重復(fù)原則(Don't repeat yourself - DRY),保留一個(gè)"通用"配置。將這些配置合并在一起,需用webpack-merge。
根據(jù)不同的"標(biāo)識(shí)" 加載應(yīng)用時(shí),自動(dòng)更換主題
vue-cli 全家桶,主要(vuex,vue-router),less ,webpack,多套同樣目錄結(jié)構(gòu)的主題靜態(tài)資源(css,img圖片)
1、把所需要改變主題的vue組件中的style全部提出來,按照目錄結(jié)構(gòu)提取到static目錄中,用less內(nèi)聯(lián)寫法防止樣式?jīng)_突。
2、利用require去動(dòng)態(tài)的給每個(gè)需要的組件渲染css和img
以上開發(fā)環(huán)境就ok了。
1、vue-cli腳手架build目錄中的webpack.prod.conf.js配置文件是webpack生產(chǎn)環(huán)境的核心配置文件。
2、webpack run build以后會(huì)把多個(gè)主題的css打包成一個(gè)大的css,會(huì)造成樣式?jīng)_突
解決辦法是在webpack的生產(chǎn)配置文件webpack.prod.conf.js中,修改一下設(shè)置,把extract的true改成false即可,會(huì)發(fā)現(xiàn)那個(gè)css文件從幾百k,變成幾十k,樣式就不會(huì)沖突了。
extract: true,此項(xiàng)是自定義項(xiàng),設(shè)置為true表示,生成獨(dú)立的文件
好!歡迎了解我們常用的網(wǎng)站建設(shè)工具——帝國CMS,其中的采集功能可實(shí)現(xiàn)自動(dòng)獲取他站文章并同步至您站點(diǎn)。盡管如此,因每個(gè)網(wǎng)站的版面構(gòu)造與形式各異,可能導(dǎo)致采集內(nèi)容在展示時(shí)產(chǎn)生形變。接下來我們簡(jiǎn)述為何文章會(huì)變形以及如何避免這一情況。
1.采集規(guī)則設(shè)置不當(dāng)
在用帝國CMS進(jìn)行采集時(shí),正確設(shè)定采集中的規(guī)則至關(guān)重要,因?yàn)檫@關(guān)系到能否精準(zhǔn)地獲取目標(biāo)網(wǎng)站內(nèi)容。若規(guī)則有誤,可能會(huì)帶來文章亂碼、排版失衡等問題。因此,我們建議您妥善調(diào)整采集規(guī)則,以避免文章變形。
2.編碼問題
由于不同網(wǎng)站采用的編碼各異,若未妥善處理編碼問題,便易致使亂碼或顯示異常。故采集中,務(wù)必先確認(rèn)網(wǎng)站編碼,再據(jù)此設(shè)定采集規(guī)則。
3. CSS樣式?jīng)_突
我們的帝國CMS在文章采集過程中,雖然會(huì)尊重原始網(wǎng)站的CSS樣式,但是這可能會(huì)引起樣式之間的沖突,從而影響到文章的正常排版顯示。因此,建議您在發(fā)布前,通過調(diào)整采集規(guī)則上的CSS特效,或在內(nèi)容編輯完成之后,手動(dòng)微調(diào)一下樣式,以確保排版效果的完美呈現(xiàn)。
4.圖片鏈接失效
在您原創(chuàng)的文章里常會(huì)包含一些圖片,但有時(shí)因?yàn)樗鼈冎赶虻氖窍鄬?duì)于當(dāng)前文檔路徑或來自其他網(wǎng)站的圖片已失效,所以可能會(huì)讓帝國CMS無法正常展示這些內(nèi)容。為了解決這個(gè)問題,我們建議您將圖片的鏈接更改為絕對(duì)路徑,或者重新將圖片上傳至自己的服務(wù)器以確保其有效鏈接。
5.鏈接轉(zhuǎn)換錯(cuò)誤
部分網(wǎng)站文章內(nèi)的鏈接,有時(shí)會(huì)因?yàn)椴杉?guī)則設(shè)定或目標(biāo)站點(diǎn)故障等原因,出現(xiàn)未能正常轉(zhuǎn)換的情況。建議您仔細(xì)查看采集規(guī)則的鏈接轉(zhuǎn)換設(shè)定是否合理,如有必要可作相應(yīng)調(diào)整。
6.特殊字符處理不當(dāng)
對(duì)于在帝國CMS系統(tǒng)中無法正常呈現(xiàn)的特殊字符(如特殊符號(hào)、表情符號(hào)等),可能會(huì)使您的文章出現(xiàn)排版問題。此時(shí),建議您嘗試在采集規(guī)則設(shè)置中對(duì)其進(jìn)行適當(dāng)處理;若無法實(shí)現(xiàn),也可以直接對(duì)文章內(nèi)容做手動(dòng)修正。
7.文章結(jié)構(gòu)錯(cuò)亂
某些網(wǎng)站的文章結(jié)構(gòu)較為繁雜,引入了許多標(biāo)題、段落及列表等元素。如此一來,在使用帝國CMS錄入時(shí),文章的結(jié)構(gòu)層次便有可能被混淆,使得文章排版顯得凌亂。為了避免這類問題,我們建議您在設(shè)定采集中,針對(duì)文章結(jié)構(gòu)進(jìn)行調(diào)整,或者通過手動(dòng)編輯完成排版。
8.人工校對(duì)和修復(fù)
雖然帝國CMS具備強(qiáng)大的采集能力,但是依然有可能因?yàn)榉N種因素導(dǎo)致部分采集來的文章存在變形現(xiàn)象。此時(shí),人工校對(duì)與修復(fù)便成為了我們堅(jiān)守的最后防線。我們會(huì)細(xì)心地進(jìn)行文章內(nèi)容審核及修正工作,以全力保證展示給大家的文章品質(zhì)符合標(biāo)準(zhǔn)哦!
在使用帝國cms進(jìn)行文章采集中,常常遇到文章變形的情況。為改善這種狀況,請(qǐng)合理解定采集規(guī)則,處理好編碼出錯(cuò)的部分,運(yùn)用CSS功能微調(diào)文章樣式,修復(fù)圖片無法顯示的問題,檢查鏈接是否轉(zhuǎn)換正確,巧妙處理特殊字符,以及調(diào)整文章結(jié)構(gòu)。此外,別忘了人工校對(duì)并進(jìn)行必要的修正以提升文章質(zhì)量與可閱讀性。希望這篇簡(jiǎn)明易懂的指南能助您一臂之力!
微前端已經(jīng)成為前端領(lǐng)域如今比較火爆的話題,關(guān)于微前端價(jià)值的討論,可以參考克軍的《擁抱云時(shí)代的前端開發(fā)框架——微前端》。微前端在技術(shù)方面,有一個(gè)始終繞不過去話題就是前端沙箱。本篇具體探討一下,在微前端領(lǐng)域如何實(shí)現(xiàn)前端沙箱。
應(yīng)用沙箱可能是微前端技術(shù)體系里面最有意思的部分。一般來說沙箱是微前端技術(shù)體系中不是必須要做的事情,因?yàn)槿绻?guī)范做的足夠好,是能夠避免掉一些變量沖突讀寫,CSS 樣式?jīng)_突的情況。但是如果你在一個(gè)足夠大的體系中,總不能僅僅通過規(guī)范來保證應(yīng)用的可靠性,還是需要技術(shù)手段去治理運(yùn)行時(shí)的一些沖突問題,這個(gè)也是沙箱方案成為微前端技術(shù)體系的一部分原因。
首先縱觀各類技術(shù)方案,有一個(gè)大前提決定了這個(gè)沙箱如何做:最終微應(yīng)用是 單實(shí)例 or 多實(shí)例 存在宿主應(yīng)用中。這個(gè)直接決定了這個(gè)沙箱的復(fù)雜度和技術(shù)方案。
? 單實(shí)例:同一個(gè)時(shí)刻只有一個(gè)微應(yīng)用實(shí)例存在,此刻瀏覽器所有瀏覽器資源都是這個(gè)應(yīng)用獨(dú)占的,方案要解決的很大程度是應(yīng)用切換的時(shí)候的清理和現(xiàn)場(chǎng)恢復(fù)。比較輕量,實(shí)現(xiàn)起來也簡(jiǎn)單。
? 多實(shí)例:資源不是應(yīng)用獨(dú)占,就要解決資源共享的情況,比如路由,樣式,全局變量讀寫,DOM. 可能需要考慮的情況比較多,實(shí)現(xiàn)較為復(fù)雜。
最開始我們的想法是:
從業(yè)務(wù)場(chǎng)景:我們可能存在的情況是當(dāng)用戶操作一個(gè)產(chǎn)品 A 的同時(shí)和另一個(gè)產(chǎn)品 B 發(fā)生了關(guān)聯(lián)操作,需要喚醒應(yīng)用 B 做操作。雖然從產(chǎn)品維度可以規(guī)避掉,比如先切到 B, 然后切回 A, 但是從某種程度上因?yàn)榧夹g(shù)的原因,我們限制了產(chǎn)品交互的發(fā)揮。
從技術(shù)角度:解決了多實(shí)例當(dāng)然單實(shí)例的場(chǎng)景也不在話下,并且單實(shí)例的方案某種程度上給編碼上帶來了一定復(fù)雜度,比如業(yè)務(wù)代碼需要自己做業(yè)務(wù)上下文的切換。
最近 qiankun 2 也轉(zhuǎn)變了思路從單實(shí)例的支持到開始支持多實(shí)例,多多少少也側(cè)面說明了,多實(shí)例是一個(gè)值得投入和技術(shù)攻克的場(chǎng)景。
基于上面的考量,我們就開始了我們 Browser VM 沙箱的實(shí)現(xiàn)探索。總結(jié)起來可以用下圖表示:
沙箱環(huán)境構(gòu)造要實(shí)現(xiàn)沙箱,我們需要隔離掉瀏覽器的原生對(duì)象,但是如何隔離,建立一個(gè)沙箱環(huán)境呢?Node 中 有 vm 模塊,來實(shí)現(xiàn)類似的能力,但是瀏覽器就不行了,但是我們可以利用了閉包的能力,利用變量作用域去模擬一個(gè)沙箱環(huán)境,比如下面的代碼:
function foo(window) {
console.log(window.document);
}
foo({
document: {};
});
比如這段代碼的輸出一定是 {}. 而不是原生瀏覽器的 document.
所以 ConsoleOS 實(shí)現(xiàn)了一個(gè) wepback 的插件在應(yīng)用代碼構(gòu)建的時(shí)候給子應(yīng)用代碼加上一層 wrap 代碼,創(chuàng)建一個(gè)閉包,把需要隔離的瀏覽器原生對(duì)象變成從下面函數(shù)閉包中獲取的,從而我們可以在應(yīng)用加載的時(shí)候,傳入模擬掉的 window,document 之類的對(duì)象。
// 打包代碼
__CONSOLE_OS_GLOBAL_HOOK__(id, function (require, module, exports, {window, document, location, history}) {
/* 打包代碼 */
})
function __CONSOLE_OS_GLOBAL_HOOK__(id, entry) {
entry(require, module, exports, {window, document, location, history})
}
當(dāng)然也可以不靠工程化的手段來實(shí)現(xiàn),也可以通過請(qǐng)求腳本,然后在運(yùn)行時(shí)拼接這段代碼,然后eval 或者 new Function, 來達(dá)到相同的目的。
原生對(duì)象模擬沙箱隔離能力有了,剩下的問題就是如何實(shí)現(xiàn)這一堆瀏覽器的原生對(duì)象了。最開始的想法是我們根據(jù) ECMA 的規(guī)范實(shí)現(xiàn)(現(xiàn)在仍然有類似的想法),但是發(fā)現(xiàn)成本太高。不過在我們各種實(shí)驗(yàn)之后,發(fā)現(xiàn)了一個(gè)很“取巧”的做法,我們可以 new iframe 對(duì)象,把里面的原生瀏覽器對(duì)象通過 contentWindow 取出來,應(yīng)為這些對(duì)象天然隔離,就省去了自己實(shí)現(xiàn)的成本。
const iframe = document.createElement( 'iframe' );
當(dāng)然里面有很多的細(xì)節(jié)需要考量,比如:
只有同域的 iframe 才能取出對(duì)應(yīng)的的 contentWindow. 所以需要提供一個(gè)宿主應(yīng)用空的同域URL來作為這個(gè) iframe 初始加載的 URL. 當(dāng)然根據(jù) HTML 的規(guī)范 這個(gè) URL 用了 about:blank 一定保證保證同域,也不會(huì)發(fā)生資源加載,但是會(huì)發(fā)生關(guān)聯(lián)的 和 這個(gè)iframe 中關(guān)聯(lián)的 history 不能被操作,這個(gè)時(shí)候路由的變換只能變成 hash 模式。
如下圖所示,我們?nèi)〕鰧?duì)應(yīng)的 iframe 中原生的對(duì)象之后,就會(huì)對(duì)特定需要隔離的對(duì)象生成對(duì)應(yīng)的 Proxy, 然后對(duì)一些屬性獲取和屬性設(shè)置,做上一些特定的設(shè)置,比如 window.document 需要返回特定的沙箱 document 而不是當(dāng)前瀏覽器的document.
class Window {
constructor(options, context, frame) {
return new Proxy(frame.contentWindow, {
set(target, name, value) {
target[name] = value;
return true;
},
get(target, name) {
switch( name ) {
case 'document':
return context.document;
default:
}
if( typeof target[ name ] === 'function' && /^[a-z]/.test( name ) ){
return target[ name ].bind && target[ name ].bind( target );
}else{
return target[ name ];
}
}
});
}
}
對(duì)于每一個(gè)對(duì)象的實(shí)現(xiàn)這里不講細(xì)節(jié)了,有興趣可以看看我們的開源之后的代碼,點(diǎn)擊前往>>>
但是為了文檔能夠被加載在同一個(gè) DOM 樹上,對(duì)于 document, 大部分的 DOM 操作的屬性和方法還是直接用的宿主瀏覽器中的 document 的屬性和方法。
由于子應(yīng)用有自己的沙箱環(huán)境,之前所有獨(dú)占式的資源現(xiàn)在都變成了應(yīng)用獨(dú)享(尤其是 location, history),所以子應(yīng)用也能同時(shí)被加載. 并且對(duì)于一些變量的我們還能在 proxy 中設(shè)置一些訪問權(quán)限的事情,從而限制子應(yīng)用的能力,比如 Cookie, LocalStoage 讀寫。
當(dāng)這個(gè) iframe 被移除時(shí),寫在 window 的變量和設(shè)置的一些 timeout 時(shí)間也會(huì)一并被移除。(當(dāng)然 DOM 事件需要沙箱記錄,然后在宿主中移除)。
總結(jié)一下,我們的沙箱可以做到如下的特性:
CSS 隔離方案相對(duì)來說比較常規(guī),常見的有:? CSS Module? 添加 css 的 namespace? Dynamic StyleSheet? Shadow DOM
CSS Module or CSS Namespace: 通過修改基礎(chǔ)組件樣式前綴來實(shí)現(xiàn)框架和微應(yīng)用依賴基礎(chǔ)組件樣式的隔離性(依賴于工程上 CSS 的預(yù)處理器編譯和運(yùn)行時(shí)基礎(chǔ)組件庫配置),同時(shí)避免全局樣式的書寫(依賴于約定或工程 lint 手段)。
Dynamic StyleSheet: 隔離方式是通過js運(yùn)行時(shí)動(dòng)態(tài)加載卸載微應(yīng)用樣式表來避免樣式的沖突,局限性一是在于站點(diǎn)框架本身或其部件(header/menu/footer)與當(dāng)前運(yùn)行的微應(yīng)用間仍存在樣式?jīng)_突的可能性,二是沒有辦法支持多個(gè)微應(yīng)用同時(shí)運(yùn)行顯示的情況。
Shadow DOM: 優(yōu)點(diǎn)是瀏覽器級(jí)別提供的樣式隔離能力,可以做到完全隔離。缺點(diǎn)在于,目前兼容性還是夠不太好,并且改造會(huì)涉及到舊應(yīng)用的業(yè)務(wù)代碼的改造,對(duì)子應(yīng)用侵入性比較高。
最終經(jīng)過實(shí)踐,我們選擇的方式是 CSS Module + 添加 CSS 的 namespace。CSS module 保證的是應(yīng)用業(yè)務(wù)樣式不沖突,Namespace 保證公共庫不沖突。我們實(shí)現(xiàn)了一個(gè) postcss 插件,會(huì)在應(yīng)用構(gòu)建的時(shí)候給所有的樣式都加上應(yīng)用前綴包括應(yīng)用公共庫的 CSS。(這樣方便做到同一個(gè) 組件庫 新舊版本樣式的兼容)。如下圖所示:
// 宿主 host app
.next-btn {
color: #eee;
}
// 子應(yīng)用 sub app
aliyun-slb .next-btn {
color: #eee;
}
//宿主中生成的節(jié)點(diǎn)
<aliyun-slb>
<!-- 子應(yīng)用的節(jié)點(diǎn) -->
</aliyun-slb>
這樣實(shí)現(xiàn)的好處在于:? 每個(gè)應(yīng)用都有 namespace, 可以多實(shí)例共存。? 不依賴特定的 CSS 預(yù)處理器。? 對(duì)于同一個(gè)庫不同版本的 CSS(如 fusion1 和 fusion2), 可以做到徹底隔離。? 鑒于上面 JS 沙箱的存在,對(duì)于一些彈窗類的組件,這個(gè)微應(yīng)用獲取的 body 實(shí)際上是宿主生成的節(jié)點(diǎn),所以彈窗會(huì)被添加到微應(yīng)用的節(jié)點(diǎn)(也就是上面的 aliyun-slb)這個(gè)節(jié)點(diǎn),樣式不會(huì)失效。
不過也會(huì)有一些問題,比如:? 嵌套應(yīng)用組件樣式優(yōu)先級(jí)的問題。(由于 CSS module 的存在,一般只會(huì)發(fā)生在公共 css 樣式中,這個(gè)就是只能盡量避免嵌套)。? fusion 不同版本庫公用字體的問題。(目前解法比較hack, 工程化手段替換掉了 next 字體的名字)。
一般來說,所以如果看完上面的文章,覺得這個(gè)沙箱方案不錯(cuò),但是又有自己的微前端體系了,想套用咋辦?
目前 ConsoleOS 的代碼已經(jīng)在 Github 上開源這里不妨可以嘗試試用一下,點(diǎn)擊前往>>>
JS 沙箱部分:如果看懂了上面關(guān)于原理的介紹可以看到其實(shí)沙箱實(shí)現(xiàn)包括兩個(gè)層面
? 原生瀏覽器對(duì)象的模擬(Browser-VM)的部分? 如何構(gòu)建一個(gè)閉包環(huán)境的部分。
Browser-VM 可以直接用起來,這部分完全是通用普適的。 但是涉及到閉包構(gòu)建的這部分,每個(gè)微前端體系不太一致,可能需要改造比如:
import { createContext, removeContext } from '@alicloud/console-os-browser-vm';
const context = await createContext();
const run = window.eval(`
(() => function({window, history, locaiton, document}) {
window.test = 1;
})()
`)
run(context);
console.log(context.window.test);
console.log(window.test);
// 操作虛擬化瀏覽器對(duì)象
context.history.pushState(null, null, '/test');
context.locaiton.hash = 'foo'
// 銷毀一個(gè) context
await removeContext( context );
當(dāng)然可以直接選擇沙箱提供好的 evalScripts 方法:
import { evalScripts } from '@alicloud/console-os-browser-vm';
const context = evalScripts('window.test = 1;')
console.log(window.test === undefined) // true
CSS 沙箱如果用webpack 構(gòu)建,可以直接配置如下:
const postcssWrap = require('@alicloud/console-toolkit-plugin-os/lib/postcssWrap')
// 下面是 webpack config
{
test: /\.css$/,
use: [
'style-loader',
{
loader: 'postcss-loader',
options: {
plugins: [
// 加入插件
postcssWrap({
stackableRoot: '.prefix',
repeat: 1
})
],
},
},
'css-loader',
],
exclude: /^node_modules$/,
}
與其干巴巴的看文章,直接試試在線 Demo 可能更有體感一些,或者試試生產(chǎn)環(huán)境的例子, 阿里云企業(yè)工作臺(tái) - 工具應(yīng)用中心 , 是阿里云集成三方應(yīng)用提供云管能力。這里每個(gè)應(yīng)用都是一個(gè)微應(yīng)用,里面涵蓋了 React, Vue, Angular 三大技術(shù)棧。
*請(qǐng)認(rèn)真填寫需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。