webpack之import 異步import


模塊標准: CommonJS、AMD、CMD、ES6 Module

CommonJS是Node.js原生支持的模塊標准. 使用module.exports和require()函數.
AMD和CMD比較相似, AMD的實現有require.js, CMD的實現有Sea.js.
ES6 Module引入importexport兩個關鍵字, 是Webpack推薦的模塊標准.

export 與 import

export

首先module.exports = ...export關鍵字不能混用, 在Wbpack中優先使用export關鍵字.
export對一個Module對象進行操作, 而不是普通的js對象, 最后module.exports賦值為該對象以導出.
使用ES6語法導出的是一個Module對象, 根據default字段, 有"默認導入"和"具名導出"兩種說法.

let value = 88;
let value2 = 66;

function printValue() {
    console.log(value);
}

// 導出"默認"變量作為一個{}對象
export default {
    value2: value, // 導出變量的同時重命名
    printValue,
};
// export default value; // 也可以將"默認"變量導出為一個變量或函數, 但不能多次導出"默認"變量
// export default value2 = value; // 重命名

// 具名導出
export { value as value2, value2 as value }; // 導出多個非默認變量, 同時重命名別名
// export { value: value2, value2: value }; // 語法錯誤
export var foo = printValue; // 導出單個非默認變量, 同時重命名
console.log({ foo }); // 現在 foo 是合法變量

import

import會判斷對應模塊入口文件(通常是/index.js)中module.exports是普通js對象還是Module對象, 從而實現兼容:

如果是Module對象, 則有默認導出和其它導出(具名導出)之分
如果是普通js對象, 那么module.exports就是默認導出

import * as A from './test'; // 等價於C, 這種語法通常在使用import關鍵字引用瀏覽器和服務器通用模塊時使用, 因為這些模塊不導出Module對象
import B from './test'; // 默認導入
const C = require('./test'); // Node.js原始require語法, 可理解為偽代碼: C = test.module.exports;
console.log({ A });
console.log({ B });
console.log({ C });

// 更新
import { default as D } from './test'; // 等價於B


高階用法

集線器

可以將一個js文件作為路由集線器, 導入其它js的非默認同時導出:

export { DefaultLoadingManager, LoadingManager } from './loaders/LoadingManager.js';

我們將之前的文件命名為test2.js, 在test1.js中路由:

export { default } from './test2'; // 導出default
export { foo } from './test2'; // 導出非默認變量foo
export * from './test2'; // 導出全部非默認變量. 也就是說導出不會包含含default字段

// 也就是說, 導出test2全部可導成員需要以下兩步
export * from './test2';
export { default } from './test2';

// 有時我們需要導入默認導出, 又需要導入普通的CommonJS導出, 可以這樣寫:
import React, { Component } from 'react';
// 那么之前的導出全部成員可以這么寫嗎? (疑問)
export *, { default } from './test2';
// 導入這樣寫可以嗎? (疑問) 不可以!!!
import * as React, { Component } from 'react';

構建通用包時, 建議不使用ES6模塊

以下四種React的引入是一樣的,顯然react包沒有使用ES6模塊:

import ReactA, { createElement as e, default as ReactB } from 'react';
import * as ReactC from 'react';
const ReactD = require('react');
console.log(ReactA === ReactB); // true
console.log(ReactA === ReactC);
console.log(ReactA === ReactD);

import一個目錄

當我們導入一個目錄時, 會嘗試執行該目錄下的index.js文件. 並且目錄優先於同名的js文件, 除非導入時顯式指定.js后綴.
在Windows下文件名不區分大小寫, 所以Index.js也可以編譯, 但是在Linux下就完蛋了...!這也算是一個坑吧

異步import

function(string loader_and_file): Promise

動態加載模塊。調用 import() 之處被視為分割點,意思着被請求的模塊和它引用的所有子模塊,會分割到一個單獨的 chunk 中。
異步import, 模塊的處理過程將作為一個分割點單獨打包為獨立模塊, 再通過ajax請求, 請求路徑是相對於引用腳本的URL, 所以對於單頁應用來說沒有問題.

// "."表示當前js文件, 使用raw-loader異步加載當前js文件的文本內容
import('!raw-loader!.').then(({ default: text }) => {
    this.setState({ code: text });
});

非入口點文件

通過異步import打包后的文件稱為非入口點文件, 文件名可以通過Webpack配置中的config.output.chunkFilename確定:

    output: {
        filename: '[name].js',
        path: DIR_DIST,
        chunkFilename: 'async/[id].js', // 此選項確定非入口塊文件的名稱
    },

Magic Comments可以通過js注釋的方式控制每一個異步import.

官方文檔

https://webpack.docschina.org/api/module-methods/
異步import及其魔法注釋
https://webpack.js.org/api/module-methods/#magic-comments

END


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM