
人的一生,會長大三次:第一次是發(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.js 和 lib.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.js 和 second.bundle.js 就像入口的名字是一樣的。
小結(jié)
今天我學(xué)會了如何使用 webpack 來對 ES6 模塊進(jìn)行打包。Webpack 4 提供了默認(rèn)的配置,今天也學(xué)到了默認(rèn)配置中的核心概念:entry 和 output。當(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)行修改,真的是焦頭爛額。
后來我明白了,在 Promise 的 then 中進(jìn)行 return,把需要賦值的變量給傳回來就可以了(catch 中的也可以傳回來),這樣在用解構(gòu)賦值語句對全局變量賦值,并且調(diào)用事件觸發(fā)的相關(guān)函數(shù),這樣整個的邏輯就會更加清晰明了,代碼結(jié)構(gòu)也會更加清楚。
今天真的是覺得自己的基本功好差,我應(yīng)該再踏實一點,好好的把一些基礎(chǔ)給補(bǔ)補(bǔ)好。
(不希望別人眼里的我是個菜比)