sea.js項目遷移到webpack

項目背景

最近參與一箇舊項目功能遷移的工做,舊項目使用到sea.jslayerjqueryart-templatebootstrapjquey.ztree等,新項目是基於vue-cliwebpack模板生成的項目。舊項目的功能是穩定可靠且經過了充分的測試,且這部分功能其中的業務本身也並不熟悉。使用常規的vue開發方式重寫整塊功能須要極大的勇氣以及耗費大量的時間精力,且結果每每吃力不討好。鑑於本身對於sea.js,jquery生態以及webpack,vue有比較深刻的的瞭解認識,一番評估下,認爲這種方案是可行的且可以在不改動業務邏輯代碼進行快速遷移。css

那麼如今咱們就開始吧。html

項目的目錄和代碼結構

先簡單介紹一下項目目錄和代碼結構,舊項目每個功能模塊以main.js爲入口。main.js用define聲明瞭一個模塊,用require引用兩個模塊的代碼,並對外暴露了一個入口renderHtml。由於舊項目都是這樣模塊的化的寫法,從而爲不動業務代碼遷移到webpack成爲了可能。vue

  • 舊項目功能模塊

image.png

  • main.js

image.png

  • 新項目目錄結構,標準的vue-cli生成的,對於vue-cli能夠移步這裏,查看更多信息

image.png

與vue組件整合

原來的sea.js的項目的功能對外暴露一個renderHtml方法,假設這個功能名稱one,內部通過一系列處理後會把html代碼渲染到id爲one的元素節點下。故咱們寫一個vue組件,對one這個功能作一個引用,並在掛載生命週期開始執行,就完成了對該功能的引用。新項目中其餘地方須要這一塊的功能,就直接使用應用vue這個組件就OK了。jquery

vue代碼大體以下webpack

<template>
  <div class="one-wrapper">
    <div class="bs-vlan-wrapper content" id="one">
    </div>
  </div>
</template>
<script>
import One from './main'
export default {
  mounted () {
    One.renderHtml()
  }
}
</script>
複製代碼

在實際開發調試過程當中main.js中的代碼能夠一點點加入,以便快速定位問題並解決。 那麼實際上會遇到哪些問題並如何解決呢,下面會闡述移植過程當中的解決方法。git

在index.html引入須要的文件

把須要的資源文件放置在static目錄下,包括依賴的js,css文件,圖片。而後把須要css和js引入到index.html文件中github

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <title></title>
    <link href="/static/js/layer/skin/layer.css" rel="stylesheet" text="text/css">
    <link href="/static/js/ztree/css/zTreeStyle/zTreeStyle.css" rel="stylesheet" text="text/css"></link>
    <link href="/static/js/font-awesome/css/font-awesome.min.css" rel="stylesheet" text="text/css">
  </head>
  <body>
    <div id="app"></div>
    <script src="/static/js/jquery/jquery-2.2.3.min.js"></script>
    <script src="/static/js/layer/layer.js"></script>
    <script src="/static/js/ztree/js/jquery.ztree.all.min.js"></script>
    <script src="/static/js/bootstrap/js/bootstrap.min.js"></script>
    <!-- built files will be auto injected -->
  </body>
</html>
複製代碼

這樣在項目中就能夠直接使用layer和等全局變量了,另外使用全局變量eslint會報警告的,因此記得在.eslintrc.js配置一下忽略layer和全局變量web

// .eslintrc.js
globals: {
  layer: false,
  $: false,
},
複製代碼

sea.js模塊代碼處理

由於webpack打包的文件已是模塊化的,並不須要define來定義模塊,故刪除js代碼中的define包裹函數ajax

define(function(require, exports, module) {
// 內部的code須要保留
})
複製代碼

sea.js中使用的是require引用文件,這個在webpack打包自然支持 可是module.exports或者exports輸出對外暴露方法,默認的babel的配置是沒法支持,故須要改變.babelrc配置。 作法是刪除presets env 下的 module=false,便可以支持。 最終.babelrc的以下所示vue-cli

{
  "presets": [
    ["env", {
      "targets": {
        "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
      }
    }],
    "stage-2"
  ],
  "plugins": ["transform-vue-jsx", "transform-runtime"]
}
複製代碼

圖片處理

咱們把圖片放到/static下後,圖片的訪問路徑多了/static前綴,故須要掃描css樣式中以及代碼中的圖片路徑就都加一下/static前綴。 實際調試過程當中,用瀏覽器訪問頁面,凡是出現404的資源引用,搜索一下對應的代碼,統統加上/static/前綴。

art-template處理

舊項目中會使用art-template讓模板html與數據融合,而後渲染到頁面上。代碼以下

var htmlTpl = require('/template/html.tpl')
var htmlTplRender = template.compile(htmlTpl);
layer.open({
  content: htmlTplRender(),
}
複製代碼

值得高興的是,art-template的最新版本支持webpack預處理。 先安裝一下art-tempate-loader

npm install art-template
npm install art-template-loader --save-dev
複製代碼

並在webpack.base.config.js加入如下loader

module.exports = {
    module: {
       {
            test: /\.tpl$/,
            loader: "art-template-loader",
            options: {
            }
        }]
    },
}
複製代碼

最後引入tpl文件,如今的tpl文件再也不使用url地址,而是使用相對文件路徑,且由於webpack已經在打包的時候預編譯,就無需compile了。最後的代碼以下

var htmlTplRender = require('/template/html.tpl');
layer.open({
content: htmlTplRender(),
}
複製代碼

bootstrap.css處理

細心的同窗,會發現bootstrap.css並無在index.html引用。由於bootstrap.css內置的樣式,其樣式名稱會對已存在的樣式產生影響。 故須要給bootstap樣式加上做用域,並在須要的功能模塊加上對應樣式名稱 新建一個文件my-bootstrap.scss,拷貝完整的bootstrap.css樣式到其中,並在項目中引用my-bootstrap.scss my-bootstrap.scss

.bs-m-wrapper {
	// 這裏拷貝完整的bootstrap.css樣式
}
複製代碼

這樣子在須要功能模塊上最外層元素加入bs-m-wrapper樣式就能夠看到原來的效果了。 特別注意的layer的彈窗是放在body下的,全部須要對彈窗也統一加上該樣式。

layer.open({
  skin: 'bs-m-wrapper',
})
複製代碼

ajax請求處理

新的項目接口也發生了變化,原來的認證信息放在cookie中,但新的接口使用了token機制,在header加入token進行認證校驗。 故須要全局攔截ajax請求,增長頭部信息。

$.ajaxSetup({
  beforeSend: function(request, opt) {
    request.setRequestHeader("token", "my token...");
  },
})
複製代碼

值得注意的是在調用$.ajax方法的時候,若是有beforeSend屬性,全局的beforeSend會被覆蓋,致使沒法加上咱們須要的token信息。故須要手動調用一下全局的beforeSend。以下所示

$.ajax({
  beforeSend: function(request, opt) {
	$.ajaxSettings.beforeSend(request, opt);
	// other
  },
});
複製代碼

至此,咱們就完成了功能的從sea.js遷移到webpack項目中了。

結語

這種方式能夠快速遷移一些複雜的功能,但美酒雖好,也不要貪杯。畢竟一個項目用到更多的庫,使用非主流的寫法,對項目成員的要求也越高,可維護性也就越低。 一路前行,且行且珍惜。

相關文章
相關標籤/搜索