zoukankan      html  css  js  c++  java
  • 关于代码分割

    省略废话。

    1.ES6之前两个比较流行的模块机制CommonJS和AMD。CommonJS模块就是对象,加载模块时加载的是拷贝;而ES6加载的是对export的变量的引用。

    2.ES6模块不是对象,使用可出现在模块顶层任何位置的export显式指定输出的代码(变量、函数、class):

    export:

      export var name='microsoft'; 

    ---another example 推荐在底部用{}输出需要的代码

      var  value_x='microsoft';    

      export { value_x,value_y ,method_y};

         如果想给export的变量改名字,可以使用as

      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)
      });

      实测可行。今天先到这里。


     

      

      

      

  • 相关阅读:
    剑指Offer替换空格
    转载类的静态成员函数和静态成员变量的使用
    最长递增子序列长度LIS
    剑指Offer二维数组中的查找
    转载C语言:浮点数在内存中的表示
    7 CICD实战 持续集成71 kubernetes与cicd
    9 深入kubernetes服务调度与编排91 健康检查高可用的守护者
    项目成功的⑤大因素
    Ucos_II2.52源码中文译注
    SIP协议中的认证方式
  • 原文地址:https://www.cnblogs.com/alan2kat/p/7298933.html
Copyright © 2011-2022 走看看