Webpack 4 系列 - 基礎(chǔ)概念

人的一生,會長大三次:第一次是發(fā)現(xiàn)自己不是世界中心的時候;第二次是發(fā)現(xiàn)自己不管如何努力,還是無能為力的時候;第三次是明知道很多事情自己無能為力,卻依然不放棄努力的時候。

??目標(biāo):自己搭建一個 TypeScript + React + Redux + RxJS 的項目模板

什么是 webpack?

webpack 一個模塊打包器,它的目的是整合一堆模塊。所以它的輸入是很多的模塊,而輸入是一個或者多個的文件。除了這個功能,webpack 還能為你做一些編譯的事情,比如把 scss變成css ,把 TypeScript 變成 JavaScript。

為什么要打包?

在過去,我們沒有辦法將我們的 javascript 代碼分成多個文件,除非使用許許多多的 <script> 標(biāo)簽。這樣我們就需要在 html 代碼中瘋狂生命 javascript 代碼的來源。比如這樣 <script src="">...</script>。這非常的不方便,所以社區(qū)想了一些解決辦法,比如 CommonJS (這個在 Node.js 中實踐了),又比如 AMD 。最終,ES6 成為了一種全新的用于導(dǎo)入導(dǎo)出的語句。

ES6 模塊

有了 ES6,模塊的語法就被定義好了,也多虧了它,我們能對模塊有一個統(tǒng)一的標(biāo)準(zhǔn),這也被寫入了 javascript 的語言規(guī)范中。

為了使用好 Webpack,有必要先將 ES6 模塊相關(guān)的語法熟悉清楚。

export

export 語句是用來創(chuàng)建 JavaScript 模塊的,你既可以用它來導(dǎo)出一個對象,或者一個函數(shù),還可以導(dǎo)出基礎(chǔ)數(shù)值(比如 1,2,3 這樣的)。

值得注意的是被導(dǎo)出的模塊是遵循 strict mode 的。

有兩種類型的模塊導(dǎo)出,分別是 named export 和 default export。

named exports

每個模塊可以導(dǎo)出多個命名導(dǎo)出:

lib.js

export function sum(a, b) {
  return a + b;
}

export function substract(a, b) {
  return a - b;
}

divide(a, b) {
  return a / b;
}

export { divide };

注意,如果你想要在聲明某個對象或函數(shù)之后,再將其導(dǎo)出,那么你需要使用花括號將它包住,像上面的 divide 函數(shù)那樣。

default exports

每個模塊僅有一個默認(rèn)導(dǎo)出:

dog.js

export default class Dog {
  bark() {
    console.log('bark!');
  }
}

import

import 語句是用來導(dǎo)入其他模塊的。

導(dǎo)入整個模塊的內(nèi)容

index.js

import * as lib from './lib.js';

console.log(lib.sum(1, 2));
console.log(lib.substract(3, 1));
console.log(lib.divide(6, 3));

https://stackoverflow.com/questions/47469095/why-export-and-import-error-in-node-js-9

你可以使用任何你喜歡的名字來命名導(dǎo)入的模塊,不一定非要使用導(dǎo)出時的命名。如果你導(dǎo)入的是某個模塊的整個內(nèi)容,如果該模塊有一個默認(rèn)的導(dǎo)出,那么這個默認(rèn)導(dǎo)出會被替換成一個叫做 default 的屬性。

index.js

import * as Dog from './dog.js';

const dog = new Dog.default();
dog.bark(); // 'bark!'

導(dǎo)入一個或多個命名導(dǎo)出

index.js

import { sum, subsctract, divide } from './lib';

console.log(lib.sum(1, 2));
console.log(lib.substract(3, 1));
console.log(lib.divide(6, 3));

在這種情況下,使用的名稱必須和導(dǎo)出文件中的方法名稱保持一致。

導(dǎo)入一個默認(rèn)的導(dǎo)出

index.js

import Dog from './dog.js';

const dog = new Dog();
dog.bark();

注意,默認(rèn)導(dǎo)出可以以任意的名稱進(jìn)行導(dǎo)入,不要求一致,所以我們可以這么做:

index.js

import Cat from './dog.js';

const dog = new Cat();
dog.bark();

ES6 模塊還支持動態(tài)導(dǎo)入功能,這個我們后面再講。你可以去 MDN 的文檔中看看更多的 exports 和 imports 的例子。

webpack 的一些基本概念

從 webpack 4 開始,webpack 不需要任何的配置就可以使用了,它有一套默認(rèn)的配置。如果你想要創(chuàng)建一個配置文件,你需要將它命名為 webpack.config.js。我們現(xiàn)在模仿一下默認(rèn)的配置,來解釋一些基本概念。

webpack.config.js

記住我們是使用 Node.js 來寫 webpack 的配置文件的,所以它會使用 CommonJS 式的模塊。

webpack.config.js 會導(dǎo)出一個單獨的對象,如果你在控制臺運行 webpack,會找到這個文件,并使用這個對象。

Entry

webpack 需要制定一個入口點,它表明 webpack 應(yīng)該從哪個模塊開始進(jìn)行打包,默認(rèn)的情況下是這樣的:

wepack.config.js

module.exports = {
  entry: './src/index.js'
}

可以使用多個入口點,但是對于單頁應(yīng)用來說,通常只需要一個就夠了。

Output

配置聲明的輸出指的是告知 webpack 應(yīng)該如何輸出打包好的文件,默認(rèn)情況下是在 ./dis/main.js

wepack.config.js

const path = require('path');

module.export = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'main.js'
  }
};

讓 webpack 跑起來!

$ npm init -y
$ npm install webpack

然后將 package.json 文件進(jìn)行如下修改:

"scripts": {
  "build": "webpack"
}

接著運行 npm run build 就可以了,你可以看到完成后,會有一個 main.js 的文件出現(xiàn)在 dist 文件夾下。這里包含了 index.jslib.js 文件中的所有代碼。

注:在 vscode 中可以安裝 live server 插件,在 public 文件夾下創(chuàng)建 index.html 引用 dist 文件夾中的 main.js,這時在控制臺查看輸出就可以看到結(jié)果了

多個入口點

上面的這些操作完全不需要你進(jìn)行任何配置就可以完成,如果你想要做點其他事情,現(xiàn)在可以創(chuàng)建一個 webpack.config.js

entries

在配置文件中,entry 這個屬性不一定是字符串類型的(代表一個入口),它也可以是對象類型的(多個入口)

webpack.config.js

module.export = {
  entry: {
    firts: './src/one.js',
    second: './src/two.js',
  }
};

通過上面的代碼,我們創(chuàng)建了兩個入口點。在什么時候可能會需要用到呢?也許你開發(fā)的是一個多頁應(yīng)用的時候,就會用到了。

outputs

出現(xiàn)了一個問題:當(dāng)我們有兩個入口的時候,我們依舊只有一個輸出,可能我們需要的是兩個入口分別對應(yīng)的輸出。怎么辦呢?要解決起來也很方便:

webpack.config.js

module.exports = {
  entry: {
    first: './src/one.js',
    second: './src/two.js',
  },
  output: {
    filename: '[name].bundle.js',
    path: path.resolve(__dirname, 'dist')
  }
}

通過上面的代碼我們可以看到不僅可以有一個輸出,是可以存在多個輸出的,它們的命名必須是唯一的,比如 first.bundle.jssecond.bundle.js 就像入口的名字是一樣的。

小結(jié)

今天我學(xué)會了如何使用 webpack 來對 ES6 模塊進(jìn)行打包。Webpack 4 提供了默認(rèn)的配置,今天也學(xué)到了默認(rèn)配置中的核心概念:entryoutput。當(dāng)然,webpack 可以做的事情遠(yuǎn)遠(yuǎn)不止這些,接下來的課程中我們會介紹更多功能。

今天的感慨

今天兵荒馬亂的對 code review 中的問題進(jìn)行了修改,由于要發(fā)版本,我的工作一直沒有完成,導(dǎo)致了別人的加班,心里蠻愧疚的。
但是,比愧疚更加讓我沮喪的是自己的技術(shù)水平真的真的太需要提高了。有一個涉及到 Promise 請求的問題,由于我在 importTasks 方法中做了太多的副作用,所以 dw 希望我將這些副作用(對全局變量的一些賦值操作,以及事件觸發(fā)的操作)集中到文件上傳完成的 onComplete 回調(diào)中去,這樣可以讓閱讀代碼的人更加清楚的明白這里的流程。
一開始我發(fā)了好久的呆,甚至都沒明白副作用是什么...一邊是急著要發(fā)版,一邊是沒理解如何針對意見進(jìn)行修改,真的是焦頭爛額。
后來我明白了,在 Promisethen 中進(jìn)行 return,把需要賦值的變量給傳回來就可以了(catch 中的也可以傳回來),這樣在用解構(gòu)賦值語句對全局變量賦值,并且調(diào)用事件觸發(fā)的相關(guān)函數(shù),這樣整個的邏輯就會更加清晰明了,代碼結(jié)構(gòu)也會更加清楚。

今天真的是覺得自己的基本功好差,我應(yīng)該再踏實一點,好好的把一些基礎(chǔ)給補(bǔ)補(bǔ)好。

(不希望別人眼里的我是個菜比)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容