Skip to content

简介

https://github.com/webpack/webpack

https://www.webpackjs.com/

https://webpack.js.org/

为什么需要构建(打包)

开发分工变化
前端越来越复杂

框架的变化
JS库(例如jquery, yui, dojo, prototype, Mootools, kissy)
->MVC(jquery, backbone.js, underscore.js) ->MVP ->MVVM(Vue, React, Angular)

语言的变化
HTML1-3 HTML3.2; HTML4.0; XHTML1.0; HTML5

CSS1; CSS2; CSS2.1; CSS3; Sass; Less; stylus

VBscript; JavaScript; CoffeeScript; TypeScript

ES6

环境的变化
浏览器、移动端

社区的变化
GitHub、npm

工具的变化
GRUNT, Gulp, webpack

开发复杂化;框架去中心化(零散);语言编译化;开发模块化

为什么使用Webpack

Vue-cli/React-starter/Angular-cli

Code-splitting

天生的模块化

JS模块化

命名空间
COMMONJS(服务器端使用)
AMD/CMD/UMD
ES 6 module

库名.类别名.方法名

1
2
3
4
5
var NameSpace = {}
NameSpace.type = NameSpace.type || {}
NameSpace.type.method = function () {

}

CommonJS
Modules/1.1.1
一个文件为一个模块
通过 module.exports 暴露模块接口
通过 require 引入模块 同步执行

AMD
Async Module Definition
使用 define 定义模块
使用 require加载模块
RequireJS
依赖前置,提前执行

CMD
Common Module Definition
一个文件为一个模块
使用 define 来定义一个模块
使用 require 来加载一个模块
SeaJS
尽可能懒执行

UMD
Universal Module Definition
通用解决方案 三个步骤:判断是否支持AMD;判断是否支持CommonJS;如果都没有 使用全局变量

ESM
EcmaScript Module
一个文件一个模块
export/import

Webpack支持
AMD(RequireJS)
ES Modules(推荐的)
CommonJS

CSS 模块化

CSS 模式设计
OOCSS; SMACSS; Atomic CSS; MCSS; AMCSS; BEM

CSS Modules

面向过程

index.html

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<!DOCTYPE html>
<html lang="zh">
<head>
  <meta charset="UTF-8">
  <title>这是最原始的网页开发</title>
</head>
<body>
  <p>这是我们的网页内容</p>
  <div id='root'></div>
  <script src="./index.js"></script>
</body>
</html>

index.js

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
var dom = document.getElementById('root')

var header = document.createElement('div')
header.innerText = 'header'
dom.append(header)

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

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

面向对象

index.html

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
<!DOCTYPE html>
<html lang="zh">
<head>
  <meta charset="UTF-8">
  <title>这是最原始的网页开发</title>
</head>
<body>
  <p>这是我们的网页内容</p>
  <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>

<script src="./index.js"></script>要放在最下面

index.js

1
2
3
4
5
var dom = document.getElementById('root')

new Header()
new Sidebar()
new Content()

header.js

1
2
3
4
5
function Header() {
    var header = document.createElement('div')
    header.innerText = 'header'
    dom.append(header)
}

sidebar.js

1
2
3
4
5
function Sidebar() {
    var sidebar = document.createElement('div')
    sidebar.innerText = 'sidebar'
    dom.append(sidebar)
}

content.js

1
2
3
4
5
function Content() {
    var content = document.createElement('div')
    content.innerText = 'content'
    dom.append(content)
}

面向对象的方式编程代码还是不是很容易维护

ES Moudule 模块引入方式

index.js

1
2
3
4
5
6
7
8
9
import Header from './header.js'
import Sidebar from './sidebar.js'
import Content from './content.js'

var dom = document.getElementById('root')

new Header()
new Sidebar()
new Content()

但是浏览器不支持这种写法

简单使用webpack

所以需要 webpack 进行翻译给浏览器

index.js

1
2
3
4
5
6
7
import Header from './header.js';
import Sidebar from './sidebar.js';
import Content from './content.js';

new Header();
new Sidebar();
new Content();

sidebar.js

1
2
3
4
5
6
7
function Sidebar() {
    var dom = document.getElementById('root');
    var sidebar = document.createElement('div');
    sidebar.innerText = 'sidebar';
    dom.append(sidebar);
}
export default Sidebar;

content.js

1
2
3
4
5
6
7
8
function Content() {
    var dom = document.getElementById('root');
    var content = document.createElement('div');
    content.innerText = 'content';
    dom.append(content);
}

export default Content;

header.js

1
2
3
4
5
6
7
8
function Header() {
    var dom = document.getElementById('root');
    var header = document.createElement('div');
    header.innerText = 'header';
    dom.append(header);
}

export default Header;

npm init
npm install webpack-cli --save-dev
npm install webpack --save-dev

使用npx webpack index.js翻译

会生成一个dist目录,目录下有一个main.js

然后可以改变index.html的写法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<!DOCTYPE html>
<html lang="zh">
<head>
  <meta charset="UTF-8">
  <title>这是最原始的网页开发</title>
</head>
<body>
  <p>这是我们的网页内容</p>
  <div id='root'></div>
  <script src="./dist/main.js"></script>
</body>
</html>

什么是模块打包工具

webpack 是一个模块打包工具

import后面的内容就是一个模块

除了 ES Moudule 模块引入方式;还有ComoonJS模块引入规范、CMD、AMD等

ES Moudule 引入方式写法

index.js

1
2
3
4
5
6
7
var Header = require('./header.js');
var Sidebar = require('./sidebar.js');
var Content = require('./content.js')

new Header();
new Sidebar();
new Content();

sidbar.js

1
2
3
4
5
6
7
function Sidebar() {
    var dom = document.getElementById('root');
    var sidebar = document.createElement('div');
    sidebar.innerText = 'sidebar';
    dom.append(sidebar);
}
module.exports = Sidebar;

content.js

1
2
3
4
5
6
7
function Content() {
    var dom = document.getElementById('root');
    var content = document.createElement('div');
    content.innerText = 'content';
    dom.append(content);
}
module.exports = Content;

header.js

1
2
3
4
5
6
7
function Header() {
    var dom = document.getElementById('root');
    var header = document.createElement('div');
    header.innerText = 'header';
    dom.append(header);
}
module.exports = Header;

最早webpack是一个js的模块打包工具
随着发展,可以打包任何形式的模块(例如css、图片等)

正确安装方式

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
➜  ~ node -v
v12.4.0
➜  ~ npm -v
6.11.3

mkdir webpack-demo
cd webpack-demo

npm init

Is this OK? (yes) yes
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
{
  "name": "webpack-demo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

添加"private": true,,去掉"main": "index.js","test": "echo \"Error: no test specified\" && exit 1"

1
2
3
4
5
6
7
8
9
{
  "name": "webpack-demo",
  "version": "1.0.0",
  "description": "",
  "private": true,
  "scripts": {},
  "author": "NoCilantro",
  "license": "ISC"
}

全局安装:

1
2
3
4
5
6
npm install webpack webpack-cli -g

➜  ~ webpack -v
4.41.0
➜  ~ webpack-cli -v
3.3.9

不建议全局安装 webpack

卸载全局的webpack

1
2
3
4
5
npm uninstall webpack webpack-cli -g
➜  ~ webpack-cli -v
zsh: command not found: webpack-cli
➜  ~ webpack -v
zsh: command not found: webpack

项目内安装 webpack

npm install webpack webpack-cli --dev或者npm install webpack webpack-cli -D

使用npx运行项目内的webpack

1
2
➜  webpack-demo npx webpack -v
4.41.0

安装指定版本的 webpack

1
2
3
4
5
6
7
8
➜  nocilantro mkdir webpack-demo2
➜  nocilantro cd webpack-demo2 
➜  webpack-demo2 npm init -y

➜  webpack-demo2 npm install webpack@4.16.5 webpack-cli -D

➜  webpack-demo2 npx webpack -v
4.16.5

在其它地方运行:

1
2
3
4
5
➜  webpack-demo2 rm -r node_modules 
➜  webpack-demo2 npm install

➜  webpack-demo2 npx webpack -v
4.16.5

配置文件

默认配置文件:webpack.config.js

在其中写入

1
2
3
4
5
6
7
8
9
const path = require('path');

module.exports = {
    entry: './index.js',
    output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname, 'bundle')
    }
}

执行npx webpack即可进行打包

生成一个bundle目录,目录中有一个bundle.js文件

可以指定配置文件:npx webpack --config xxx.js

npm scripts 方式进行打包:

修改package.json文件中scripts中的内容

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
{
  "name": "lesson",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "bundle": "webpack"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^4.41.0",
    "webpack-cli": "^3.3.9"
  }
}

此时运行npm run bundle即可进行打包

webpack-cli使得可以在命令行中使用命令

打包知识点

1
entry: './src/index.js',

1
2
3
entry: {
  main: './src/index.js',
}

的简写

1
2
    Asset      Size  Chunks             Chunk Names
bundle.js  1.36 KiB       0  [emitted]  main

所以Chunk Namesmain

默认modeproduction

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
const path = require('path');

module.exports = {
    mode: 'production',
    entry: './src/index.js',
    output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname, 'dist')
    }
}

production会将打包出的内容压缩

设置为development
mode: 'development',
不会压缩打包出的代码