2-1 webpack究竟是什么

简介

这章主要是为了引出webpack。

1. 普通的网页写法

首先,来看一下,不考虑使用任何工具,如何来写一个网页:

<!--index.html-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>original-pop</title>
</head>
<body>
    <div id="root"></div>
    <script src="./index.js"></script>
</body>
</html>
// index.js
var dom = document.getElementById('root');

var header = document.createElement('div');
header.innerText = 'header';
// 这里,原视屏使用append,看append,appendChild和innerHtml,innerText的区别和性能
dom.appendChild(header);

var sidebar = document.createElement('div');
sidebar.innerText = 'sidebar';
dom.appendChild(sidebar);

var content = document.createElement('div');
content.innerText = 'content';
dom.appendChild(content);

可以看到,最简单的方法,就是将html,js,css放到不同的文件,然后通过src或者href引入。这里我们先不关注css,主要来看js。

这里的js我们采用pop的写法。如果内容越来越多,内容越来越多,难以管理与维护。我们先采用oop的写法来修改上述文件。

2. 使用oop改造

使用oop改造的代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>original-oop</title>
</head>
<body>
    <div id="root"></div>
    <script src="./header.js"></script>
    <script src="./sidebar.js"></script>
    <script src="./content.js"></script>
    <script src="./index.js"></script>
</body>
</html>
// index.js
var dom = document.getElementById('root');

new Header();
new Sidebar();
new Content();
// header.js
function Header() {
    var header = document.createElement('div');
    header.innerText = 'header';
    dom.appendChild(header);
}
// sidebar.js
function Sidebar() {
    var sidebar = document.createElement('div');
    sidebar.innerText = 'sidebar';
    dom.appendChild(sidebar);
}
// content.js
function Content() {
    var content = document.createElement('div');
    content.innerText = 'content';
    dom.appendChild(content);
}

可以看到,面向对象的写法使各部分代码职责更清晰,维护更方便。但也带来了一些新的问题:

  1. 拆成多个文件导致需要加载的资源更多
  2. 从代码中看不出文件的依赖关系
  3. 不能保证加载顺序,会产生依赖错误

前面两点大家好理解,对于第三点呢,我们可以看一下例子。这里,调整html中对js的引用顺序,将index.js的引入放在最上面,如下:

    <script src="./index.js"></script>
    <script src="./header.js"></script>
    <script src="./sidebar.js"></script>
    <script src="./content.js"></script>

打开网页会发现报如下错误:


依赖出错.png

那么如何解决这三个问题呢?

3. 使用打包工具webpack

我们先来分析一下这三个问题,文件太大了,我们想拆成多个文件,这是出于编写者的需要,明确各个文件之间的依赖关系也是出于编写者的需要,而保证加载顺序是运行时需要。如果仍然使用一个文件,上述问题都不会有,但是编写和维护困难。
那么,换个思路,编写时拆成多个文件,明确指定依赖关系。然后利用工具将所有文件合并到一起,不就解决了所有问题吗?webpack就是这样的一个打包工具。
我们先用esmodule,改造一下上面的js代码,让他符合我们的意图:

// index.js
import Header from './header';
import Sidebar from './sidebar';
import Content from './content';

new Header();
new Sidebar();
new Content();
// header.js
export default function Header() {
    var dom = document.getElementById('root');
    var header = document.createElement('div');
    header.innerText = 'header';
    dom.appendChild(header);
}
// sidebar.js
export default function Sidebar() {
    var dom = document.getElementById('root');
    var sidebar = document.createElement('div');
    sidebar.innerText = 'sidebar';
    dom.appendChild(sidebar);
}
// content.js
export default function Content() {
    var dom = document.getElementById('root');
    var content = document.createElement('div');
    content.innerText = 'content';
    dom.appendChild(content);
}

我们的意图很明确了,指定了各个模块的依赖关系,但是直接运行是不行的,浏览器并不识别esmodule语法。我们需要借助webpack来实现。在当前代码根目录下,进行如下下操作:

1. npm init 或者 npm init -y
2. npm install webpack webpack-cli -D(或者-save-dev),webpack4推荐局部安装,原因见
// https://segmentfault.com/q/1010000013395159/a-1020000014395848
// 这里如果报错:npm ERR! Unexpected end of JSON input while parsing near '...":"3.4.1","devDepende'。可以尝试用cnpm来安装。
3. npx webpack index.js

我们发现在根目录下生成了一个文件夹dist,下面有一个main.js文件,这就是webpack根据模块间的依赖关系打包生成的新文件。我们引入这个文件。

<!--index.html-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>esmodule-oop</title>
</head>
<body>
    <div id="root"></div>
    <script src="./dist/main.js"></script>
</body>
</html>

okay,访问网页,成功。

4. 总结

webpack是一个打包工具。通过webpack,使用esmodule,解决oop的三个问题

  1. 拆成多个文件导致加载资源更多 -> 只用引入一个文件
  2. 从代码中看不出文件的依赖关系 -> 在引入文件中指定依赖关系
  3. 不能保证加载顺序,会产生依赖错误 -> 已制定依赖关系,严格按照依赖关系执行

引申

  1. append,appendChild和innerHtml,innerText的区别和性能
  2. pop和oop的区别
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。