亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

詳解webpack分包及異步加載套路

 更新時(shí)間:2017年06月29日 11:31:51   作者:蘋果小蘿卜  
本篇文章主要介紹了詳解webpack分包及異步加載套路,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧

最近一個(gè)小項(xiàng)目是用webpack來(lái)進(jìn)行構(gòu)建的。其中用到了webpack分包異步加載的功能。今天抽時(shí)間看了下webpack打包后的文件,大致弄明白了webpack分包及異步加載的套路。

由于這個(gè)小項(xiàng)目是用自己寫的一個(gè)路由,路由定義好了不同路徑對(duì)應(yīng)下的模板及邏輯代碼:

webpack配置文件:

 var path = require('path'),
 DashboardPlugin = require('webpack-dashboard/plugin'),
 HtmlWebpackPlugin = require('html-webpack-plugin'),
 webpack = require('webpack'),
 ExtractTextPlugin = require('extract-text-webpack-plugin');

var PATHS = {
 app: path.join(__dirname, 'src'),
 dist: path.join(__dirname, 'dist')
}

var PKG = require('./package.json');
var TARGET = process.env.npm_lifecycle_event; //獲取當(dāng)前正在運(yùn)行的腳本名稱

var isProduction = function() {
 return process.env.NODE_ENV === 'production';
}



module.exports ={
 entry: {
 'index': path.join(__dirname, 'src/index.js'),
 'lib': ['./src/lib/js/index.js'],
 },
 //filename是主入口文件的名稱,即對(duì)應(yīng)的entry
 //chunkFilename對(duì)應(yīng)的是非主入口文件的名稱,chunk
 output: {
 path: PATHS.dist,
 publicPath: '/static/taxi-driver/', //publicPath 的話是打包的時(shí)候生成的文件鏈接,如果是在生產(chǎn)環(huán)境當(dāng)然是用服務(wù)器地址,如果是開發(fā)環(huán)境就是用本地靜態(tài)服務(wù)器的地址
 filename: 'js/register/[name].js',
 chunkFilename: 'js/register/[name].js',
 //TODO: build文件中加入hash值
 },
 //生成source-map文件
 devtool: isProduction ? null : 'source-map',
 devServer: {
 proxy: {
  '/api/*': {
  target: 'http://localhost:3000',
  secure: false
  }
 }
 },
 module: {
 loaders: [
  {
  test: /\.js$/,
  exclude: /node_modules|picker.min.js/,
  loader: 'babel'
  },
  {
  test: /\.less$/,
  loader: ExtractTextPlugin.extract('style', 'css!less')
  },
  {
  test: /\.html$/,
  loader: 'raw'
  },
  {
  test: /\.css$/,
  loader: ExtractTextPlugin.extract('style', 'css')
  },
  {
  test: /\.json$/,
  loader: 'json'
  }
 ]
 },
 resolve: {
 alias: {
  src: path.join(__dirname, 'src'),
  modules: path.join(__dirname, 'src/modules'),
  lessLib: path.join(__dirname, 'src/lib/less'), 
  jsLib: path.join(__dirname, 'src/lib/js'),
  components: path.join(__dirname, 'src/components')
 },
 extensions: ['', '.js', '.less', '.html', '.json'],
 },
 plugins: [
 new HtmlWebpackPlugin({
  title: '認(rèn)證資料',
  template: './dist/assets/info.html',
  inject: 'body',
  filename: 'pages/register/index.html' //輸出html文件的位置
 }),
 new DashboardPlugin(),
 new ExtractTextPlugin('css/register/style.css'), //將引入的樣式文件單獨(dú)抽成style.css文件并插入到head標(biāo)簽當(dāng)中,帶有路徑時(shí),最后打包
 new webpack.optimize.CommonsChunkPlugin({
  name: 'common',
  filename: 'js/register/common.js',
  minChunks: 3
 })
 ]
}

接下來(lái)是定義好的路由文件:

 const Router = new Route();
 
 Route
 .addRoute({
  path: 'path1',
  viewBox: '.public-container',
  template: require('modules/path1/index.html'),
  pageInit() {
  //webpack提供的分包的API. require.ensure
  require.ensure([], () => {
   let controller = require('modules/path1/controller');
   Router.registerCtrl('path1', new controller('.public-container'));
  }, 'path1');
  }
 })
 .addRoute({
  path: 'path2',
  viewBox: '.public-container',
  template: require('modules/path2/index.html'),
  pageInit() {
  require.ensure([], () => {
   let controller = require('modules/path2/controller');
   Router.registerCtrl('path2', new controller('.public-container'));
  }, 'path2');
  }
 });

最后webpack會(huì)將這2個(gè)需要異步加載的模塊,分別打包成path1.js和path2.js.

當(dāng)頁(yè)面的路徑為:

http://localhost:8080/pages/register/#/path1時(shí),會(huì)加載path1.js文件
http://localhost:8080/pages/register/#/path2時(shí),會(huì)加載path2.js文件.

再來(lái)看看webpack打包后的文件:

其中在common.js中, webpack定義了一個(gè)全局函數(shù)webpackJsonp.這個(gè)全局函數(shù)在項(xiàng)目一啟動(dòng)后就定義好。
局部函數(shù)__webpack_require__用以在某一個(gè)模塊中初始化或者調(diào)用其他的模塊方法。同時(shí)這個(gè)函數(shù)還有一個(gè)靜態(tài)方法__webpack_require__.e這個(gè)方法就是用來(lái)異步加載js文件的。

接下來(lái)一步一步的看:

 //common.js
 (function(modules) {
 //modules用來(lái)保存所有的分包,它是一個(gè)數(shù)組,數(shù)組每個(gè)元素對(duì)應(yīng)的都是callback,每個(gè)分包都是通過數(shù)字來(lái)進(jìn)行標(biāo)識(shí)的
 
 //定義好的全局函數(shù)webpackJsonp
 //大家可以看看其他打包好的文件,例如index.js, path1.js和path2.js文件.都是webpackJsonp()這種的形式,大家用過JSONP應(yīng)該會(huì)很好理解。首先在前端定義好函數(shù),然后后端下發(fā)組裝好的函數(shù)js文件,前端獲取到這個(gè)文件后就可以立即進(jìn)行執(zhí)行了
 var parentJsonpFunction = window["webpackJsonp"];
 window["webpackJsonp"] = function webpackJsonpCallback(chunkIds, moreModules) {
  var moduleId, chunkId, i = 0, callbacks = [];
 for(;i < chunkIds.length; i++) {
  chunkId = chunkIds[i];
  if(installedChunks[chunkId])
  callbacks.push.apply(callbacks, installedChunks[chunkId]);
  installedChunks[chunkId] = 0;
 }
  //這個(gè)全局函數(shù)會(huì)將各個(gè)分包緩存到modules
 for(moduleId in moreModules) {
  modules[moduleId] = moreModules[moduleId];
 }
 if(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules);
 while(callbacks.length)
  callbacks.shift().call(null, __webpack_require__);
  //用以啟動(dòng)整個(gè)應(yīng)用
 if(moreModules[0]) {
  installedModules[0] = 0;
  return __webpack_require__(0);
 }
 };
 })([]);

 // The require function
  //通過數(shù)字標(biāo)識(shí)的moduleId
 function __webpack_require__(moduleId) {

 // Check if module is in cache
 if(installedModules[moduleId])
  return installedModules[moduleId].exports;

 // Create a new module (and put it into the cache)
 var module = installedModules[moduleId] = {
  exports: {},
  id: moduleId,
  loaded: false
 };

 // Execute the module function
 modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);

 // Flag the module as loaded
 module.loaded = true;

 // Return the exports of the module
 return module.exports;
 }

 // This file contains only the entry chunk.
 // The chunk loading function for additional chunks
  //異步加載函數(shù)
 __webpack_require__.e = function requireEnsure(chunkId, callback) {
 // "0" is the signal for "already loaded"
 if(installedChunks[chunkId] === 0)
  return callback.call(null, __webpack_require__);

 // an array means "currently loading".
 if(installedChunks[chunkId] !== undefined) {
  installedChunks[chunkId].push(callback);
 } else {
   //創(chuàng)建script表情,請(qǐng)求js文件
  // start chunk loading
  installedChunks[chunkId] = [callback];
  var head = document.getElementsByTagName('head')[0];
  var script = document.createElement('script');
  script.type = 'text/javascript';
  script.charset = 'utf-8';
  script.async = true;

  script.src = __webpack_require__.p + "js/register/" + ({"0":"index","1":"path1","2":"path2"}[chunkId]||chunkId) + ".js";
  head.appendChild(script);
 }
 };

 // expose the modules object (__webpack_modules__)
 __webpack_require__.m = modules;

 // expose the module cache
 __webpack_require__.c = installedModules;

 // __webpack_public_path__
  //配置文件中定義的publicPath,build完后加載文件的路徑
 __webpack_require__.p = "/static/taxi-driver/";
})

在最后輸出的index.html文件中首先加載的是這個(gè)common.js文件,然后是入口文件index.js。因?yàn)檫@個(gè)實(shí)例代碼里面沒有很多共用文件,因此webpack自己提供的commonChunkPlugin這個(gè)插件并沒有起到作用,本來(lái)作為共用文件的xRoute.js因此也被打包進(jìn)入了index.js.

 webpackJsonp([0, 3], [
 /* 0 */
/***/ function(module, exports, __webpack_require__) {

 'use strict';

 __webpack_require__(1);

 __webpack_require__(8);

/***/ },
/* 1 */
/* 2 */
/* 3 */
//....
/* 8 */
 ])

index.js文件在common.js后加載,加載完后即開始執(zhí)行.大家還記得webpackJsonp這個(gè)全局函數(shù)里面的倒數(shù)3行代碼吧。就是用以調(diào)用這里:

 /* 0 */
 function(module, exports, __webpack_require__) {

 'use strict';

 __webpack_require__(1);

 __webpack_require__(8);

}

其中模塊Id為1和8的內(nèi)容請(qǐng)查看相應(yīng)文件, 其中模塊1為我定義的路由文件,在執(zhí)行模塊1的代碼前,會(huì)加載模塊2的內(nèi)容,模塊2的內(nèi)容為我定義的路由庫(kù)。

接下來(lái)就看下模塊1中路由定義的具體內(nèi)容:

 /* 1 */
/***/ function(module, exports, __webpack_require__) {

 'use strict';

 Object.defineProperty(exports, "__esModule", {
 value: true
 });
 
 //加載路由庫(kù)
 var _index = __webpack_require__(2);
 //實(shí)例化一個(gè)路由
 var Router = new _index.Route();
 //定義好的路由規(guī)則
 Router.home('path1').addRoute({
 path: 'path1',
 viewBox: '.public-container',
 //模板文件,為模塊4
 template: __webpack_require__(4),
 pageInit: function pageInit() {
 //這個(gè)方法是在common.js中__webpack_require__的靜態(tài)方法,用來(lái)異步加載js。
 //異步加載js的文件(即chunk)用來(lái)數(shù)字來(lái)標(biāo)識(shí),chunk的順序從0開始.
 //這里path1.js的chunk num為1,大家可以回過頭到common.js的__webpack_require__.e方法里面看看,里面已經(jīng)做好了chunk num和模塊文件的映射, chunk 1對(duì)應(yīng)的模塊文件為path1.js,chunk 2對(duì)用的模塊文件為path2.js
 //__webpack_require__.e()接收的第二個(gè)參數(shù)為異步加載模塊后的回調(diào). 當(dāng)path1.js被加載完后,在modules里面進(jìn)行了緩存.這時(shí)就可以通過模塊id去獲取這個(gè)模塊。然后進(jìn)行初始化等后續(xù)的操作
  __webpack_require__.e/* nsure */(1, function () {
  var controller = __webpack_require__(6);
  Router.registerCtrl('path1', new controller('.public-container'));
  });
 }
 }).addRoute({
 path: 'path2',
 viewBox: '.public-container',
 //模板文件,為模塊5
 template: __webpack_require__(5),
 pageInit: function pageInit() {
  __webpack_require__.e/* nsure */(2, function () {
  var controller = __webpack_require__(7);
  Router.registerCtrl('path2', new controller('.public-container'));
  });
 }
 });

 Router.bootstrap();

 exports.default = Router;

/***/ },

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評(píng)論