關於代碼分割

省略廢話。css

1.ES6以前兩個比較流行的模塊機制CommonJS和AMD。CommonJS模塊就是對象,加載模塊時加載的是拷貝;而ES6加載的是對export的變量的引用。vue

2.ES6模塊不是對象,使用可出如今模塊頂層任何位置的export顯式指定輸出的代碼(變量、函數、class):webpack

export:git

  export var name='microsoft'; github

---another example 推薦在底部用{}輸出須要的代碼web

  var  value_x='microsoft';    vue-router

  export { value_x,value_y ,method_y};vuex

     若是想給export的變量更名字,可使用asapi

  export { value_x,value_y  as  alias_name ,method_y};數組

  export function fn_name(){};

      *export的變量是動態綁定其所在模塊的。好比setTimeout後改變value_x的值,接收者獲得的value_x也會定時改變。

import:

  import { value_x,mothed_y } from strUrl;

  value_x,mothed_y的名稱必須與 strUr 中export的名稱相同。若是想給import的變量更名字,可使用as

  import { value_x as value_z,mothed_y } from strUrl;

  *import具備提高效果。

  *import會執行所加載的模塊。

  *import命令中接收的變量名要在{}中

總體加載:

  能夠用*指定一個對象,全部import的東西都加載到這對象上:

  import * as mod from strUrl;

  var x=mod.value_x;

  也能夠用module命令:

  module mod from strUrl;

  var x=mod.value_x;

export default:

  上面說了import命令中加載的變量名稱要和export輸出的名稱一致,咱們也能夠在輸出模塊中用export default指定默認輸出:

    export default function(){};  --好比一個匿名函數或對象

  而後本身在加載的時候給接收的函數/對象命名:

    import customName from strUrl;

    *import後不用加{}。由於export default在模塊中只能使用一次,只輸出一個變量/方法/class。

    *不管export default輸出的是否是匿名,都視爲匿名。

    *除了默認輸出外還想加載其餘變量:

    import customName,{value_x,method_x} from strUrl;

    *export * from strOtherMod 命令,先加載strOtherMod 再將其輸出,*會忽略strOtherMod 的默認輸出。

-------------------------------------------------------------分割線----------------------------------------------------------------

在實際生產中經常使用到webpack。webpack有code-spliting功能,容許咱們分割代碼,實現模塊靜態/動態加載。

webpack有三種代碼分離方法:

1.打包時在entry部署要打包幾個chunk。

2.使用CommonsChunkPlugin插件去重和分離chunk。

3.Dynamic Imports:經過模塊的內聯函數動態導入代碼(重點)。

 import:

  webpack使用import語法來實現模塊的動態導入,這裏import會生成一個promise對象:import('path/to/module') -> Promise,如下是官方例子:

    if ( module.hot ) {
      import('lodash').then(_ => {
      // Do something with lodash (a.k.a '_')...
      })
    }    --記住,then()中return的變量會做爲後續then(param)的參數prama

  在這裏,import()會被webpack看成一個代碼分割點(split point),所要import的文件會被另外打包成一個chunk,等須要時再加載。

  使用時報錯:

    Module build failed: SyntaxError: D:/te/src/js/third.js: 'import' and 'export' may only appear at the top level (251:1)

 

    根據webpack官網案例,案例中能成功,這裏的報錯有說是webpack並無按正確的語法來對待import,有網友說須要插件如:syntax-dynamic-import,

  也有說babel的presets要加latest和es2015,個人babel配置和presets是沒問題的,估計是插件,這裏留下這個問題。

  lazy-loading(須要時加載):  

    button.onclick = e => import(/* webpackChunkName: "print" */ './print')

              .then(module => {
                var print = module.default;
                 print();
           });

    官網例子很淺顯,觸發某個事件的時候再import模塊,就像圖片廊等用戶滾動的時候再加載更多圖片一個道理。

CommonJS:

  webpack也支持commonjs,commonjs模塊主要分爲三塊:模塊引用require、模塊定義exports、模塊標誌module(即模塊自己)。

  在服務器端,require(strUrl)是同步的,因爲服務器在本地硬盤讀取文件,速度很快,故而沒問題,但瀏覽器端必須使用異步方法,於是有了AMD/CMD。

    webpack實現的commonjs有:

  1.require(strUrl);   --同步

  2.require.resolve(strUrl)  --檢索(或者說返回)strUrl模塊的id。

  3.require.cache(module.id)  

    --模塊被require後只執行一次,也只返回一個exports對象。官網表示,在某些極端狀況會須要屢次require同一個模塊,也即重複執行某個require(獲取module並執行回調);

    於是能夠執行那面的代碼:

      delete require.cache[require.resolve("dependency")];

    大意是刪除本來加載完的模塊的id,讓js能夠再次加載模塊並執行回調。

  4.require.ensure([dependencies],callback(require),chunkName_str);

  --這是webpack的require api裏惟一一個能夠實現異步加載的函數。

    第一個參數是模塊依賴的名稱數組(這些依賴是執行callback須要的);

    第二個是回調,qi,其形參require容許咱們執行進一步的require.ensure;

    第三個是chunk名稱,require.ensure的代碼會被打包到另外一個chunk乘機加載,該參數就是這個chunk的名稱。同名的chunk會被打包在一塊兒。

//------------------------------------------------------------------------分割線---------------------------------------------------------------------------------------------------------------

 

使用vue的異步組件:

  vue定義全局組件的方式是:

    Vue.component('name',optionObj);

  文檔說,「Vue.js 容許將組件定義爲一個工廠函數,動態地解析組件的定義」:

--------------------------------------引用-------------------------------------------

    Vue.component('async-example', function (resolve, reject) {
      setTimeout(function () {
          // Pass the component definition to the resolve callback
          resolve({
          template: '<div>I am async!</div>'
          })
        }, 1000)
      })

  工廠函數接收一個 resolve 回調,在收到從服務器下載的組件定義時調用。也能夠調用 reject(reason) 指示加載失敗。

  這裏 setTimeout 只是爲了演示。怎麼獲取組件徹底由你決定。

---------------------------------------------------------------------------------------------

  因此肯定第一點:vue中異步組件的實現,是把 Vue.component('name',optionObj)中optionObj替換爲一個函數,

  這個函數執行異步任務,獲取組件的定義並執行回調。

  第二點是:當須要用到異步組件的時候,每每是模塊已經足夠大,這時候每每是使用.vue單文件組件,自包含template、css和其餘options。

  我我的對文檔中的方法不太能理解:  

     Vue.component('async-webpack-example', function (resolve) {
      // 這個特殊的 require 語法告訴 webpack
      // 自動將編譯後的代碼分割成不一樣的塊,
      // 這些塊將經過 Ajax 請求自動下載。
      require(['./my-async-component'], resolve)
    })

    後來有人解釋說;這總方式是能夠的,但省略了一些生產上的具體代碼,實際上應該這樣寫:

        

  <script>
    import Vue from 'vue'

    const name_ = Vue.component('name', function (resolve) {
      require(['./service-search.vue'], resolve)
    })

    export default{
      data(){
      return {}
      },
      methods: {},
      components: {
      name: name_       //也能夠更簡便地將function (resolve){}替換這裏的name_
      }
    }
</script>

vue路由:

  另外,我也在學習vue路由時使用異步組件,用的是github上同行的寫法:

  import Vue from 'vue'
  import App from './App.vue'
  import VueRouter from 'vue-router'
  import VueResource from 'vue-resource'
  import Vuex from 'vuex'

  const setting = resolve => require.ensure([], () => resolve(require('./components/setting.vue')), 'setting'); 

  Vue.use(VueRouter);
  Vue.use(VueResource);
  Vue.use(Vuex);

  const routes=[
    {path:'/setting',component:setting},
  ];
  const router = new VueRouter({
    mode: 'history',
    base: __dirname,
    routes
  })

  new Vue({
    router,
    store,
    el: '#app',
    render: h => h(App)
  });

  實測可行。今天先到這裏。

相關文章
相關標籤/搜索