国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

前端模塊化雜記

GitCafe / 1736人閱讀

摘要:入口模塊返回的賦值給總結(jié)在剖析了整體的流程之后,可以看到相關(guān)的技術(shù)細(xì)節(jié)還是比較清晰的,學(xué)無止境引用混合使用詳解的語法前端模塊化規(guī)范

前言

CMDAMD簡(jiǎn)介

Commonjs簡(jiǎn)介

Module簡(jiǎn)介

Common和Module的區(qū)別

Module與webpack

Module與Babel

一些問題

總結(jié)

引用

前言

前端模塊化在近幾年層出不窮,有Node的CommonJs,也有屬于client端的CMD/AMD模式,而ES6本身也出現(xiàn)了Modules,再加上Webpack以及babel的普及,雖然在代碼中經(jīng)常使用到這些用法,但是如果不去深入研究,總覺得是一個(gè)黑魔法,無法探測(cè)一些問題的根源。

AMD/CMD簡(jiǎn)介

事實(shí)上,隨著打包工具和Babel在前端工程化的世界里大放異彩,AMD/CMD也在逐步退出歷史的舞臺(tái),這里簡(jiǎn)單的介紹下其用法及語義。

AMD及其用法

AMD 即Asynchronous Module Definition,中文名是異步模塊定義的意思。代表(require.js)

/** main.js 入口文件/主模塊 **/
// 首先用config()指定各模塊路徑和引用名
require.config({
  baseUrl: "js/lib",
  paths: {
    "jquery": "jquery.min",  //實(shí)際路徑為js/lib/jquery.min.js
    "underscore": "underscore.min",
  }
});
// 執(zhí)行基本操作
require(["jquery","underscore"],function($,_){
  // some code here
});

CMD及其用法

CMD 即Common Module Definition, 中文名是通用模塊定義的意思。代表(Sea.js)

/** sea.js **/
// 定義模塊 math.js
define(function(require, exports, module) {
    var $ = require("jquery.js");
    var add = function(a,b){
        return a+b;
    }
    exports.add = add;
});
// 加載模塊
seajs.use(["math.js"], function(math){
    var sum = math.add(1+2);
});

兩者的區(qū)別

1、AMD推崇依賴前置,在定義模塊的時(shí)候就要聲明其依賴的模塊
2、CMD推崇就近依賴,只有在用到某個(gè)模塊的時(shí)候再去require

Commonjs簡(jiǎn)介

Commonjs的應(yīng)用主要是在Node應(yīng)用中。

通過require引入文件, 文件內(nèi)部則通過module.export暴露,如下a 就是 module.export

// 引入某個(gè)文件
const a = require("some.js")

// some.js

module.export = {
  ...
  // some code
}

除去module.export,Commonjs還有一個(gè)exports屬性(不推薦使用), 事實(shí)上exports就是module.export

// 對(duì)外輸出接口可以添加變量
var exports = module.exports;
exports.area = function (r) {
  return Math.PI * r * r;
};

exports.circumference = function (r) {
  return 2 * Math.PI * r;
};

// 注意不要直接對(duì)exports賦值,這樣會(huì)切斷exports和module的關(guān)系
exports = a // 不要這么做
Module簡(jiǎn)介

ES6的Module是官方正式推出的模塊化寫法,雖然目前有挺多瀏覽器還不支持,不過我們可以利用babel將其轉(zhuǎn)換,話不多說,先介紹下Module的基本用法。

ES6的module主要是以import導(dǎo)入想要的對(duì)象,export 和 export default導(dǎo)出對(duì)象

import x from "some.js"  // 引用some.js中的export default
import {a, b} from "some.js"  // 引用some.js的 export a 和 export b
import x, {a, b} from "some.js"  // 引用 some.js的 export default 和 export a 和 export b

// some.js
const x = () => {}

export const a = () => {}
export const b = () => {}

export default x

因?yàn)閕mport是編譯時(shí)加載,所以import命令具有提升效果,會(huì)提升到整個(gè)模塊的頭部,首先執(zhí)行。

// some code
...
...

import xxx from "xxx" // 提升到最頂部
Common和Module的區(qū)別

1. 加載的時(shí)機(jī)不同

Common是運(yùn)行時(shí)加載的,可以使用變量或者表達(dá)式,如:

 const "f" + "oo" =  require("my_modules")

Module是編譯時(shí)加載的,不可以使用變量或者表達(dá)式, 編譯時(shí)加載效率較高。

2.暴露出的接口不同

Common暴露出來的是值的拷貝,也就是說,一旦輸出一個(gè)值,模塊內(nèi)部的變化就影響不到這個(gè)值。

// lib.js
var counter = 3;
function incCounter() {
  counter++;
}
module.exports = {
  counter: counter,
  incCounter: incCounter,
}; 
// main.js
var counter = require("./lib").counter;
var incCounter = require("./lib").incCounter;

console.log(counter);  // 3
incCounter();
console.log(counter); // 3

Module則相反, 輸出的是值的引用。

Module與webpack

webpack本身維護(hù)了一套模塊系統(tǒng),這套模塊系統(tǒng)兼容了所有前端歷史進(jìn)程下的模塊規(guī)范,包括 amd commonjs es6 等,為了看module在webpack中是怎么運(yùn)行的,我們可以看一下下面簡(jiǎn)單的代碼:

// webpack

const path = require("path");

module.exports = {
  entry: "./a.js",
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "bundle.js",
  }
};
// a.js
import a from "./c";

export default "a.js";
console.log(a);
// c.js

export default 333;

打包后的代碼如下:

(function(modules) {

  
  function __webpack_require__(moduleId) {
    var module =  {
      i: moduleId,
      l: false,
      exports: {}
    };
    modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
    return module.exports;
  }

  return __webpack_require__(0);
})([
  (function (module, __webpack_exports__, __webpack_require__) {

    // 引用 模塊 1
    "use strict";
    Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
    /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__c__ = __webpack_require__(1);

/* harmony default export */ __webpack_exports__["default"] = ("a.js");
console.log(__WEBPACK_IMPORTED_MODULE_0__c__["a" /* default */]);

  }),
  (function (module, __webpack_exports__, __webpack_require__) {

    // 輸出本模塊的數(shù)據(jù)
    "use strict";
    /* harmony default export */ __webpack_exports__["a"] = (333);
  })
]);

簡(jiǎn)化一波代碼再看,可以看出打包后實(shí)際上是一個(gè)立即執(zhí)行函數(shù),并且入?yún)楦鱾€(gè)module文件, 最后返回的是__webpack_require__(0)

(function(modules) {

  
  function __webpack_require__(moduleId) {
  }

  return __webpack_require__(0);
})([module1, module2]);

ok, 我們繼續(xù)看__webpack_require__函數(shù),可以看出它是調(diào)用了我們的入口模塊,同時(shí)傳入了module相關(guān)的屬性,以及函數(shù)本身

function __webpack_require__(moduleId) {
    var module =  {
      i: moduleId,
      l: false,
      exports: {}
    };
    modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
    return module.exports;
  }

那么繼續(xù)追溯到入口模塊,也就是我們的第一個(gè)參數(shù)我們可以看到入口模塊又調(diào)用了 __webpack_require__(1) 去引用入?yún)?shù)組里的第2個(gè)函數(shù)。
然后會(huì)將入?yún)⒌?webpack_exports 對(duì)象添加 default 屬性,并賦值。
這里我們就能看到模塊化的實(shí)現(xiàn)原理,這里的 webpack_exports 就是這個(gè)模塊的 module.exports 通過對(duì)象的引用傳參,間接的給 module.exports 添加屬性。
最后會(huì)將 module.exports return 出來。就完成了 webpack_require 函數(shù)的使命。

function (module, __webpack_exports__, __webpack_require__) {

/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__c__ = __webpack_require__(1);

    /* harmony default export */ __webpack_exports__["default"] = ("a.js");
    console.log(__WEBPACK_IMPORTED_MODULE_0__c__["a" /* default */]);

  }

至此,我們可以看出module其實(shí)在webpack中,最后的打包結(jié)果。

Module與Babel

雖然webpack可以打包轉(zhuǎn)換我們的module,但通常我們都會(huì)引入babel來對(duì)ES6轉(zhuǎn)成ES5的代碼,而Moduel屬于ES6,也會(huì)被轉(zhuǎn)譯。

事實(shí)上,babel是將module轉(zhuǎn)換成commonjs,這樣 webpack 就無需再做處理,直接使用 webpack 運(yùn)行時(shí)定義的 webpack_require 處理。

不過babel在轉(zhuǎn)換的時(shí)候,會(huì)有一些特殊的處理, 像下面

首先 export 的時(shí)候, 會(huì)添加一個(gè)__esModule屬性到exports,是為了表明這是經(jīng)過轉(zhuǎn)換的module

export default a

// 轉(zhuǎn)換成  
Object.defineProperty(exports, "__esModule", {
  value: true
});

exports.default = a;

再看 轉(zhuǎn)出的
轉(zhuǎn)出其實(shí)會(huì)多一個(gè)_interopRequireDefault函數(shù),就是為了處理default這個(gè)屬性

import d from "d"  
// 轉(zhuǎn)化后
var _d = require("d");

var _d2 = _interopRequireDefault(_d);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
一些問題

1.為什么有的地方使用 require 去引用一個(gè)模塊時(shí)需要加上 default?

我們?cè)谏衔?babel 對(duì)導(dǎo)出模塊的轉(zhuǎn)換提到,es6 的 export default 都會(huì)被轉(zhuǎn)換成 exports.default,即使這個(gè)模塊只有這一個(gè)輸出。

2.經(jīng)常在各大UI組件引用的文檔上會(huì)看到說明 import { button } from "xx-ui" 這樣會(huì)引入所有組件內(nèi)容,需要添加額外的 babel 配置,比如 babel-plugin-component?

import { Button, Select } from "element-ui"
// 轉(zhuǎn)換成
var a = require("element-ui");
var Button = a.Button;
var Select = a.Select;

babel-plugin-component就做了一件事,將 import { Button, Select } from "element-ui" 轉(zhuǎn)換成了

import Button from "element-ui/lib/button"
import Select from "element-ui/lib/select"  

3.我們?cè)跒g覽一些 npm 下載下來的 UI 組件模塊時(shí)(比如說 element-ui 的 lib 文件下),看到的都是 webpack 編譯好的 js 文件,可以使用 import 或 require 再去引用。但是我們平時(shí)編譯好的 js 是無法再被其他模塊 import 的,這是為什么?

通過 webpack 模塊化原理章節(jié)給出的 webpack 配置編譯后的 js 是無法被其他模塊引用的,webpack 提供了 output.libraryTarget 配置指定構(gòu)建完的 js 的用途。入口模塊返回的 module.exports 賦值給 module.exports
總結(jié)

在剖析了整體的流程之后,可以看到相關(guān)的技術(shù)細(xì)節(jié)還是比較清晰的,學(xué)無止境~~~

引用

import、require、export、module.exports 混合使用詳解
Module的語法
前端模塊化
Commonjs規(guī)范

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/108907.html

相關(guān)文章

  • Webpack系列-第一篇基礎(chǔ)雜記

    摘要:系列文章系列第一篇基礎(chǔ)雜記系列第二篇插件機(jī)制雜記系列第三篇流程雜記前言公司的前端項(xiàng)目基本都是用來做工程化的,而雖然只是一個(gè)工具,但內(nèi)部涉及到非常多的知識(shí),之前一直靠來解決問題,之知其然不知其所以然,希望這次能整理一下相關(guān)的知識(shí)點(diǎn)。 系列文章 Webpack系列-第一篇基礎(chǔ)雜記 Webpack系列-第二篇插件機(jī)制雜記 Webpack系列-第三篇流程雜記 前言 公司的前端項(xiàng)目基本都是用...

    Batkid 評(píng)論0 收藏0
  • React-flux雜記

    摘要:簡(jiǎn)介是一種搭建客戶端的應(yīng)用架構(gòu),更像是一種模式而不是一個(gè)框架。 簡(jiǎn)介 Flux是一種搭建WEB客戶端的應(yīng)用架構(gòu),更像是一種模式而不是一個(gè)框架。 特點(diǎn) 單向數(shù)據(jù)流 showImg(https://segmentfault.com/img/remote/1460000018128072?w=1300&h=708); 與MVC的比較 1.傳統(tǒng)的MVC如下所示(是一個(gè)雙向數(shù)...

    王巖威 評(píng)論0 收藏0
  • Webpack系列-第三篇流程雜記

    摘要:最后執(zhí)行了的回調(diào)函數(shù),觸發(fā)了事件點(diǎn),并回到函數(shù)的回調(diào)函數(shù)觸發(fā)了事件點(diǎn)執(zhí)行對(duì)于當(dāng)前模塊,或許存在著多個(gè)依賴模塊。 系列文章 Webpack系列-第一篇基礎(chǔ)雜記 Webpack系列-第二篇插件機(jī)制雜記 Webpack系列-第三篇流程雜記 前言 本文章個(gè)人理解, 只是為了理清webpack流程, 沒有關(guān)注內(nèi)部過多細(xì)節(jié), 如有錯(cuò)誤, 請(qǐng)輕噴~ 調(diào)試 1.使用以下命令運(yùn)行項(xiàng)目,./scrip...

    xorpay 評(píng)論0 收藏0
  • webpack系列-插件機(jī)制雜記

    摘要:系列文章系列第一篇基礎(chǔ)雜記系列第二篇插件機(jī)制雜記系列第三篇流程雜記前言本身并不難,他所完成的各種復(fù)雜炫酷的功能都依賴于他的插件機(jī)制。的插件機(jī)制依賴于一個(gè)核心的庫,。是什么是一個(gè)類似于的的庫主要是控制鉤子函數(shù)的發(fā)布與訂閱。 系列文章 Webpack系列-第一篇基礎(chǔ)雜記 Webpack系列-第二篇插件機(jī)制雜記 Webpack系列-第三篇流程雜記 前言 webpack本身并不難,他所完成...

    Neilyo 評(píng)論0 收藏0
  • React-生命周期雜記

    摘要:前言自從發(fā)布之后,更新速度日新月異,而生命周期也隨之改變,雖然原有的一些生命周期函數(shù)面臨廢棄,但理解其背后更新的機(jī)制也是一種學(xué)習(xí)在這里根據(jù)官方文檔以及社區(qū)上其他優(yōu)秀的文章進(jìn)行一個(gè)對(duì)于生命周期的總結(jié),大致上分為以下三個(gè)模塊新老生命周期的區(qū)別為 前言 自從React發(fā)布Fiber之后,更新速度日新月異,而生命周期也隨之改變,雖然原有的一些生命周期函數(shù)面臨廢棄,但理解其背后更新的機(jī)制也是一種...

    KoreyLee 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<