整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          Vue換膚,開發環境實現方案,生產環境樣式沖突解決方案

          ue作為三大主流前端開發框架之一,近年來用戶群發展迅速,用其開發的軟件項目越來越多。

          開發環境和生產環境

          vue開發環境(development)和生產環境(production)的構建目標差異很大。

          開發環境中,我們需要具有強大的,具有實時重新加載(live reloading)或熱模塊替換(hot module replacement)能力的 source map 和 localhost server。

          生產環境中,我們的目標則轉向于關注更小的 bundle,更輕量的 source map,以及更優化的資源,以改善加載時間。

          遵循邏輯分離原則,通常為每個環境編寫彼此獨立的 webpack 配置。同時遵循不重復原則(Don't repeat yourself - DRY),保留一個"通用"配置。將這些配置合并在一起,需用webpack-merge。

          業務需求

          根據不同的"標識" 加載應用時,自動更換主題

          前提條件

          vue-cli 全家桶,主要(vuex,vue-router),less ,webpack,多套同樣目錄結構的主題靜態資源(css,img圖片)

          開發環境實現

          1、把所需要改變主題的vue組件中的style全部提出來,按照目錄結構提取到static目錄中,用less內聯寫法防止樣式沖突。

          2、利用require去動態的給每個需要的組件渲染css和img

          以上開發環境就ok了。

          生產環境實現

          1、vue-cli腳手架build目錄中的webpack.prod.conf.js配置文件是webpack生產環境的核心配置文件。

          2、webpack run build以后會把多個主題的css打包成一個大的css,會造成樣式沖突

          解決辦法是在webpack的生產配置文件webpack.prod.conf.js中,修改一下設置,把extract的true改成false即可,會發現那個css文件從幾百k,變成幾十k,樣式就不會沖突了。

          extract: true,此項是自定義項,設置為true表示,生成獨立的文件

          好!歡迎了解我們常用的網站建設工具——帝國CMS,其中的采集功能可實現自動獲取他站文章并同步至您站點。盡管如此,因每個網站的版面構造與形式各異,可能導致采集內容在展示時產生形變。接下來我們簡述為何文章會變形以及如何避免這一情況。

          1.采集規則設置不當

          在用帝國CMS進行采集時,正確設定采集中的規則至關重要,因為這關系到能否精準地獲取目標網站內容。若規則有誤,可能會帶來文章亂碼、排版失衡等問題。因此,我們建議您妥善調整采集規則,以避免文章變形。

          2.編碼問題

          由于不同網站采用的編碼各異,若未妥善處理編碼問題,便易致使亂碼或顯示異常。故采集中,務必先確認網站編碼,再據此設定采集規則。

          3. CSS樣式沖突

          我們的帝國CMS在文章采集過程中,雖然會尊重原始網站的CSS樣式,但是這可能會引起樣式之間的沖突,從而影響到文章的正常排版顯示。因此,建議您在發布前,通過調整采集規則上的CSS特效,或在內容編輯完成之后,手動微調一下樣式,以確保排版效果的完美呈現。

          4.圖片鏈接失效

          在您原創的文章里常會包含一些圖片,但有時因為它們指向的是相對于當前文檔路徑或來自其他網站的圖片已失效,所以可能會讓帝國CMS無法正常展示這些內容。為了解決這個問題,我們建議您將圖片的鏈接更改為絕對路徑,或者重新將圖片上傳至自己的服務器以確保其有效鏈接。

          5.鏈接轉換錯誤

          部分網站文章內的鏈接,有時會因為采集規則設定或目標站點故障等原因,出現未能正常轉換的情況。建議您仔細查看采集規則的鏈接轉換設定是否合理,如有必要可作相應調整。

          6.特殊字符處理不當

          對于在帝國CMS系統中無法正常呈現的特殊字符(如特殊符號、表情符號等),可能會使您的文章出現排版問題。此時,建議您嘗試在采集規則設置中對其進行適當處理;若無法實現,也可以直接對文章內容做手動修正。

          7.文章結構錯亂

          某些網站的文章結構較為繁雜,引入了許多標題、段落及列表等元素。如此一來,在使用帝國CMS錄入時,文章的結構層次便有可能被混淆,使得文章排版顯得凌亂。為了避免這類問題,我們建議您在設定采集中,針對文章結構進行調整,或者通過手動編輯完成排版。

          8.人工校對和修復

          雖然帝國CMS具備強大的采集能力,但是依然有可能因為種種因素導致部分采集來的文章存在變形現象。此時,人工校對與修復便成為了我們堅守的最后防線。我們會細心地進行文章內容審核及修正工作,以全力保證展示給大家的文章品質符合標準哦!

          在使用帝國cms進行文章采集中,常常遇到文章變形的情況。為改善這種狀況,請合理解定采集規則,處理好編碼出錯的部分,運用CSS功能微調文章樣式,修復圖片無法顯示的問題,檢查鏈接是否轉換正確,巧妙處理特殊字符,以及調整文章結構。此外,別忘了人工校對并進行必要的修正以提升文章質量與可閱讀性。希望這篇簡明易懂的指南能助您一臂之力!

          微前端已經成為前端領域如今比較火爆的話題,關于微前端價值的討論,可以參考克軍的《擁抱云時代的前端開發框架——微前端》。微前端在技術方面,有一個始終繞不過去話題就是前端沙箱。本篇具體探討一下,在微前端領域如何實現前端沙箱。

          背景

          應用沙箱可能是微前端技術體系里面最有意思的部分。一般來說沙箱是微前端技術體系中不是必須要做的事情,因為如果規范做的足夠好,是能夠避免掉一些變量沖突讀寫,CSS 樣式沖突的情況。但是如果你在一個足夠大的體系中,總不能僅僅通過規范來保證應用的可靠性,還是需要技術手段去治理運行時的一些沖突問題,這個也是沙箱方案成為微前端技術體系的一部分原因。

          首先縱觀各類技術方案,有一個大前提決定了這個沙箱如何做:最終微應用是 單實例 or 多實例 存在宿主應用中。這個直接決定了這個沙箱的復雜度和技術方案。

          ? 單實例:同一個時刻只有一個微應用實例存在,此刻瀏覽器所有瀏覽器資源都是這個應用獨占的,方案要解決的很大程度是應用切換的時候的清理和現場恢復。比較輕量,實現起來也簡單。

          ? 多實例:資源不是應用獨占,就要解決資源共享的情況,比如路由,樣式,全局變量讀寫,DOM. 可能需要考慮的情況比較多,實現較為復雜。

          最開始我們的想法是:

          從業務場景:我們可能存在的情況是當用戶操作一個產品 A 的同時和另一個產品 B 發生了關聯操作,需要喚醒應用 B 做操作。雖然從產品維度可以規避掉,比如先切到 B, 然后切回 A, 但是從某種程度上因為技術的原因,我們限制了產品交互的發揮。

          從技術角度:解決了多實例當然單實例的場景也不在話下,并且單實例的方案某種程度上給編碼上帶來了一定復雜度,比如業務代碼需要自己做業務上下文的切換。

          最近 qiankun 2 也轉變了思路從單實例的支持到開始支持多實例,多多少少也側面說明了,多實例是一個值得投入和技術攻克的場景。

          基于上面的考量,我們就開始了我們 Browser VM 沙箱的實現探索。總結起來可以用下圖表示:

          JavaScript 沙箱實現

          沙箱環境構造要實現沙箱,我們需要隔離掉瀏覽器的原生對象,但是如何隔離,建立一個沙箱環境呢?Node 中 有 vm 模塊,來實現類似的能力,但是瀏覽器就不行了,但是我們可以利用了閉包的能力,利用變量作用域去模擬一個沙箱環境,比如下面的代碼:

          function foo(window) {
            console.log(window.document);
          }
          
          foo({
              document: {};
          });

          比如這段代碼的輸出一定是 {}. 而不是原生瀏覽器的 document.

          所以 ConsoleOS 實現了一個 wepback 的插件在應用代碼構建的時候給子應用代碼加上一層 wrap 代碼,創建一個閉包,把需要隔離的瀏覽器原生對象變成從下面函數閉包中獲取的,從而我們可以在應用加載的時候,傳入模擬掉的 window,document 之類的對象。

          // 打包代碼
          __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})
          }

          當然也可以不靠工程化的手段來實現,也可以通過請求腳本,然后在運行時拼接這段代碼,然后eval 或者 new Function, 來達到相同的目的。

          原生對象模擬沙箱隔離能力有了,剩下的問題就是如何實現這一堆瀏覽器的原生對象了。最開始的想法是我們根據 ECMA 的規范實現(現在仍然有類似的想法),但是發現成本太高。不過在我們各種實驗之后,發現了一個很“取巧”的做法,我們可以 new iframe 對象,把里面的原生瀏覽器對象通過 contentWindow 取出來,應為這些對象天然隔離,就省去了自己實現的成本。

          const iframe = document.createElement( 'iframe' );

          當然里面有很多的細節需要考量,比如:

          只有同域的 iframe 才能取出對應的的 contentWindow. 所以需要提供一個宿主應用空的同域URL來作為這個 iframe 初始加載的 URL. 當然根據 HTML 的規范 這個 URL 用了 about:blank 一定保證保證同域,也不會發生資源加載,但是會發生關聯的 和 這個iframe 中關聯的 history 不能被操作,這個時候路由的變換只能變成 hash 模式。

          如下圖所示,我們取出對應的 iframe 中原生的對象之后,就會對特定需要隔離的對象生成對應的 Proxy, 然后對一些屬性獲取和屬性設置,做上一些特定的設置,比如 window.document 需要返回特定的沙箱 document 而不是當前瀏覽器的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 ];
                  }
                }
              });
            }
          }

          對于每一個對象的實現這里不講細節了,有興趣可以看看我們的開源之后的代碼,點擊前往>>>

          但是為了文檔能夠被加載在同一個 DOM 樹上,對于 document, 大部分的 DOM 操作的屬性和方法還是直接用的宿主瀏覽器中的 document 的屬性和方法。

          由于子應用有自己的沙箱環境,之前所有獨占式的資源現在都變成了應用獨享(尤其是 location, history),所以子應用也能同時被加載. 并且對于一些變量的我們還能在 proxy 中設置一些訪問權限的事情,從而限制子應用的能力,比如 Cookie, LocalStoage 讀寫。

          當這個 iframe 被移除時,寫在 window 的變量和設置的一些 timeout 時間也會一并被移除。(當然 DOM 事件需要沙箱記錄,然后在宿主中移除)。

          總結一下,我們的沙箱可以做到如下的特性:

          CSS 隔離

          CSS 隔離方案相對來說比較常規,常見的有:? CSS Module? 添加 css 的 namespace? Dynamic StyleSheet? Shadow DOM

          CSS Module or CSS Namespace: 通過修改基礎組件樣式前綴來實現框架和微應用依賴基礎組件樣式的隔離性(依賴于工程上 CSS 的預處理器編譯和運行時基礎組件庫配置),同時避免全局樣式的書寫(依賴于約定或工程 lint 手段)。

          Dynamic StyleSheet: 隔離方式是通過js運行時動態加載卸載微應用樣式表來避免樣式的沖突,局限性一是在于站點框架本身或其部件(header/menu/footer)與當前運行的微應用間仍存在樣式沖突的可能性,二是沒有辦法支持多個微應用同時運行顯示的情況。

          Shadow DOM: 優點是瀏覽器級別提供的樣式隔離能力,可以做到完全隔離。缺點在于,目前兼容性還是夠不太好,并且改造會涉及到舊應用的業務代碼的改造,對子應用侵入性比較高。

          最終經過實踐,我們選擇的方式是 CSS Module + 添加 CSS 的 namespace。CSS module 保證的是應用業務樣式不沖突,Namespace 保證公共庫不沖突。我們實現了一個 postcss 插件,會在應用構建的時候給所有的樣式都加上應用前綴包括應用公共庫的 CSS。(這樣方便做到同一個 組件庫 新舊版本樣式的兼容)。如下圖所示:

          // 宿主 host app
          .next-btn {
              color: #eee;
          }
          
          // 子應用 sub app
          aliyun-slb .next-btn {
              color: #eee;
          }
          
          //宿主中生成的節點
          <aliyun-slb>
              <!-- 子應用的節點 -->
          </aliyun-slb>

          這樣實現的好處在于:? 每個應用都有 namespace, 可以多實例共存。? 不依賴特定的 CSS 預處理器。? 對于同一個庫不同版本的 CSS(如 fusion1 和 fusion2), 可以做到徹底隔離。? 鑒于上面 JS 沙箱的存在,對于一些彈窗類的組件,這個微應用獲取的 body 實際上是宿主生成的節點,所以彈窗會被添加到微應用的節點(也就是上面的 aliyun-slb)這個節點,樣式不會失效。

          不過也會有一些問題,比如:? 嵌套應用組件樣式優先級的問題。(由于 CSS module 的存在,一般只會發生在公共 css 樣式中,這個就是只能盡量避免嵌套)。? fusion 不同版本庫公用字體的問題。(目前解法比較hack, 工程化手段替換掉了 next 字體的名字)。

          如何和其他體系結合

          一般來說,所以如果看完上面的文章,覺得這個沙箱方案不錯,但是又有自己的微前端體系了,想套用咋辦?

          目前 ConsoleOS 的代碼已經在 Github 上開源這里不妨可以嘗試試用一下,點擊前往>>>

          JS 沙箱部分:如果看懂了上面關于原理的介紹可以看到其實沙箱實現包括兩個層面

          ? 原生瀏覽器對象的模擬(Browser-VM)的部分? 如何構建一個閉包環境的部分。

          Browser-VM 可以直接用起來,這部分完全是通用普適的。 但是涉及到閉包構建的這部分,每個微前端體系不太一致,可能需要改造比如:

          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);
          
          // 操作虛擬化瀏覽器對象
          context.history.pushState(null, null, '/test');
          context.locaiton.hash = 'foo'
          
          // 銷毀一個 context
          await removeContext( context );

          當然可以直接選擇沙箱提供好的 evalScripts 方法:

          import { evalScripts } from '@alicloud/console-os-browser-vm';
          
          const context = evalScripts('window.test = 1;')
          
          console.log(window.test === undefined) // true

          CSS 沙箱如果用webpack 構建,可以直接配置如下:

          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$/,
          }

          Try Live Demo

          與其干巴巴的看文章,直接試試在線 Demo 可能更有體感一些,或者試試生產環境的例子, 阿里云企業工作臺 - 工具應用中心 , 是阿里云集成三方應用提供云管能力。這里每個應用都是一個微應用,里面涵蓋了 React, Vue, Angular 三大技術棧。


          主站蜘蛛池模板: 亚洲国产日韩一区高清在线| 日韩毛片基地一区二区三区| 国产精品xxxx国产喷水亚洲国产精品无码久久一区 | 精品一区二区三区波多野结衣| 日韩欧美一区二区三区免费观看| 亚洲一区爱区精品无码| 麻豆精品一区二区综合av| 91香蕉福利一区二区三区| 色狠狠色噜噜Av天堂一区| 日韩精品电影一区亚洲| 午夜福利无码一区二区| 亚洲综合一区二区| 中文字幕一区二区视频| 亚洲午夜精品第一区二区8050 | 国产一区二区三区91| 国产精品 一区 在线| www一区二区三区| 精品国产香蕉伊思人在线在线亚洲一区二区 | 精品国产毛片一区二区无码 | 亚洲一区免费观看| 亚洲无删减国产精品一区| 日韩人妻精品无码一区二区三区| 精品国产免费一区二区三区| 中文字幕在线无码一区| 国产激情一区二区三区| 中文字幕一区二区区免| 国模无码一区二区三区不卡| 国产一区二区三区在线视頻| 久久精品国产一区二区三区肥胖 | 精品人妻系列无码一区二区三区| 日韩一区精品视频一区二区| 国产高清在线精品一区| 久久精品日韩一区国产二区| 国产女人乱人伦精品一区二区| 国产一区二区精品久久岳√| www亚洲精品少妇裸乳一区二区 | 亚洲欧美国产国产一区二区三区| 无码aⅴ精品一区二区三区 | 国产精品合集一区二区三区| 亚洲.国产.欧美一区二区三区| 波多野结衣在线观看一区二区三区|