人的一生,会长大三次:第一次是发现自己不是世界中心的时候;第二次是发现自己不管如何努力,还是无能为力的时候;第三次是明知道很多事情自己无能为力,却依然不放弃努力的时候。
💪目标:自己搭建一个 TypeScript + React + Redux + RxJS 的项目模板
什么是 webpack?
webpack 一个模块打包器,它的目的是整合一堆模块。所以它的输入是很多的模块,而输入是一个或者多个的文件。除了这个功能,webpack 还能为你做一些编译的事情,比如把 scss变成css ,把 TypeScript 变成 JavaScript。
为什么要打包?
在过去,我们没有办法将我们的 javascript 代码分成多个文件,除非使用许许多多的 <script>
标签。这样我们就需要在 html 代码中疯狂生命 javascript 代码的来源。比如这样 <script src="">...</script>
。这非常的不方便,所以社区想了一些解决办法,比如 CommonJS (这个在 Node.js 中实践了),又比如 AMD 。最终,ES6 成为了一种全新的用于导入导出的语句。
ES6 模块
有了 ES6,模块的语法就被定义好了,也多亏了它,我们能对模块有一个统一的标准,这也被写入了 javascript 的语言规范中。
为了使用好 Webpack,有必要先将 ES6 模块相关的语法熟悉清楚。
export
export
语句是用来创建 JavaScript 模块的,你既可以用它来导出一个对象,或者一个函数,还可以导出基础数值(比如 1,2,3 这样的)。
值得注意的是被导出的模块是遵循 strict mode
的。
有两种类型的模块导出,分别是 named export 和 default export。
named exports
每个模块可以导出多个命名导出:
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 };
注意,如果你想要在声明某个对象或函数之后,再将其导出,那么你需要使用花括号将它包住,像上面的 divide
函数那样。
default exports
每个模块仅有一个默认导出:
dog.js
export default class Dog {
bark() {
console.log('bark!');
}
}
import
import 语句是用来导入其他模块的。
导入整个模块的内容
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
你可以使用任何你喜欢的名字来命名导入的模块,不一定非要使用导出时的命名。如果你导入的是某个模块的整个内容,如果该模块有一个默认的导出,那么这个默认导出会被替换成一个叫做 default 的属性。
index.js
import * as Dog from './dog.js';
const dog = new Dog.default();
dog.bark(); // 'bark!'
导入一个或多个命名导出
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));
在这种情况下,使用的名称必须和导出文件中的方法名称保持一致。
导入一个默认的导出
index.js
import Dog from './dog.js';
const dog = new Dog();
dog.bark();
注意,默认导出可以以任意的名称进行导入,不要求一致,所以我们可以这么做:
index.js
import Cat from './dog.js';
const dog = new Cat();
dog.bark();
ES6 模块还支持动态导入功能,这个我们后面再讲。你可以去 MDN 的文档中看看更多的 exports 和 imports 的例子。
webpack 的一些基本概念
从 webpack 4 开始,webpack 不需要任何的配置就可以使用了,它有一套默认的配置。如果你想要创建一个配置文件,你需要将它命名为 webpack.config.js
。我们现在模仿一下默认的配置,来解释一些基本概念。
webpack.config.js
记住我们是使用 Node.js 来写 webpack 的配置文件的,所以它会使用 CommonJS 式的模块。
webpack.config.js
会导出一个单独的对象,如果你在控制台运行 webpack,会找到这个文件,并使用这个对象。
Entry
webpack 需要制定一个入口点,它表明 webpack 应该从哪个模块开始进行打包,默认的情况下是这样的:
wepack.config.js
module.exports = {
entry: './src/index.js'
}
可以使用多个入口点,但是对于单页应用来说,通常只需要一个就够了。
Output
配置声明的输出指的是告知 webpack 应该如何输出打包好的文件,默认情况下是在 ./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 文件进行如下修改:
"scripts": {
"build": "webpack"
}
接着运行 npm run build
就可以了,你可以看到完成后,会有一个 main.js
的文件出现在 dist
文件夹下。这里包含了 index.js
和 lib.js
文件中的所有代码。
注:在 vscode 中可以安装 live server 插件,在 public 文件夹下创建
index.html
引用dist
文件夹中的main.js
,这时在控制台查看输出就可以看到结果了
多个入口点
上面的这些操作完全不需要你进行任何配置就可以完成,如果你想要做点其他事情,现在可以创建一个 webpack.config.js
entries
在配置文件中,entry 这个属性不一定是字符串类型的(代表一个入口),它也可以是对象类型的(多个入口)
webpack.config.js
module.export = {
entry: {
firts: './src/one.js',
second: './src/two.js',
}
};
通过上面的代码,我们创建了两个入口点。在什么时候可能会需要用到呢?也许你开发的是一个多页应用的时候,就会用到了。
outputs
出现了一个问题:当我们有两个入口的时候,我们依旧只有一个输出,可能我们需要的是两个入口分别对应的输出。怎么办呢?要解决起来也很方便:
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
就像入口的名字是一样的。
小结
今天我学会了如何使用 webpack 来对 ES6 模块进行打包。Webpack 4 提供了默认的配置,今天也学到了默认配置中的核心概念:entry
和 output
。当然,webpack 可以做的事情远远不止这些,接下来的课程中我们会介绍更多功能。
今天的感慨
今天兵荒马乱的对 code review 中的问题进行了修改,由于要发版本,我的工作一直没有完成,导致了别人的加班,心里蛮愧疚的。
但是,比愧疚更加让我沮丧的是自己的技术水平真的真的太需要提高了。有一个涉及到 Promise
请求的问题,由于我在 importTasks
方法中做了太多的副作用,所以 dw 希望我将这些副作用(对全局变量的一些赋值操作,以及事件触发的操作)集中到文件上传完成的 onComplete
回调中去,这样可以让阅读代码的人更加清楚的明白这里的流程。
一开始我发了好久的呆,甚至都没明白副作用是什么...一边是急着要发版,一边是没理解如何针对意见进行修改,真的是焦头烂额。
后来我明白了,在 Promise
的 then
中进行 return
,把需要赋值的变量给传回来就可以了(catch
中的也可以传回来),这样在用解构赋值语句对全局变量赋值,并且调用事件触发的相关函数,这样整个的逻辑就会更加清晰明了,代码结构也会更加清楚。
今天真的是觉得自己的基本功好差,我应该再踏实一点,好好的把一些基础给补补好。
(不希望别人眼里的我是个菜比)
网友评论