前言
为毛使用webpack
伴随着移动互联的大潮,当今越来越多的网站已经从网页模式进化到了 Webapp 模式。它们运行在现代的高级浏览器里,使用 HTML5、 CSS3、 ES6 等更新的技术来开发丰富的功能,网页已经不仅仅是完成浏览的基本需求,并且webapp通常是一个单页面应用,每一个视图通过异步的方式加载,这导致页面初始化和使用过程中会加载越来越多的 JavaScript 代码,这给前端开发的流程和资源组织带来了巨大的挑战。
前端开发和其他开发工作的主要区别,首先是前端是基于多语言、多层次的编码和组织工作,其次前端产品的交付是基于浏览器,这些资源是通过增量加载的方式运行到浏览器端,如何在开发环境组织好这些碎片化的代码和资源,并且保证他们在浏览器端快速、优雅的加载和更新,就需要一个模块化系统,这个理想中的模块化系统是前端工程师多年来一直探索的难题。
什么是webpack
webpack是一个模块打包器,它将根据模块的依赖关系进行静态分析,然后将这些模块按照指定的规则生成对应的静态资源
这里引用webpack官网的一张图来方便大家理解
webpack的特点
代码拆分
Webpack 有两种组织模块依赖的方式,同步和异步。异步依赖作为分割点,形成一个新的块。在优化了依赖树后,每一个异步区块都作为一个文件被打包。
Loader
Webpack 本身只能处理原生的 JavaScript 模块,但是 loader 转换器可以将各种类型的资源转换成 JavaScript 模块。这样,任何资源都可以成为 Webpack 可以处理的模块。
智能解析
Webpack 有一个智能解析器,几乎可以处理任何第三方库,无论它们的模块形式是 CommonJS、 AMD 还是普通的 JS 文件。甚至在加载依赖的时候,允许使用动态表达式 require(“./templates/” + name + “.jade”)。
插件系统
Webpack 还有一个功能丰富的插件系统。大多数内容功能都是基于这个插件系统运行的,还可以开发和使用开源的 Webpack 插件,来满足各式各样的需求。
运行速度
Webpack 使用异步 I/O 和多级缓存提高运行效率,这使得 Webpack 能够以令人难以置信的速度快速增量编译。
开始
安装
1.安装node.js node 自导了软件管理器 npm webpack需要node.js v0.6以上的支持
npm install webpack -g
此时webpack已经安装到全局环境下,可以通过命令行 webpack -h试试
通常我们会将webpack安装到项目的依赖中,这样我们就可以使用项目本地版本的webpack
npm install webpack --save-dev
使用
首先创建一个静态页面index.html和一个js文件入口entry.js
<!--index.html-->
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<script src="bundle.js"></script>
</body>
</html>
entry.js
document.write('It Work.')
然后编译entry.js并打包放到bundle.js
$weback entry.js bundle.js
用游览器打开index.html将会看到it work
接下来添加一个mudule.js并修改入口entry.js
//module.js
module.eports='It works from module.js.'
// entry.js
document.write('It works.')
document.write(require('./module.js')) // 添加模块
重新打包webpack entry.js bundle.js 然后刷新页面看到变化It works. It works from module.js
Hash: 279c7601d5d08396e751
Version: webpack 1.12.2
Time: 63ms
Asset Size Chunks Chunk Names
bundle.js 1.57 kB 0 [emitted] main
[0] ./entry.js 66 bytes {0} [built]
[1] ./module.js 43 bytes {0} [built]
webpack会分析入口文件,解析包含依赖关系的各文件,这些文件都打包到bundle.js
webpack会给每个模块分配一个唯一的ID 并通过这个ID 索引和访问模块,在页面启动时,会先执行entry.js中的代码,其他模块会在运行require的时候再执行
Loader
webpack本身只能处理javaScript模块,如果要处理其他类型的文件,就需要使用loader进行转换
loader可以理解为模块和资源转换器,它本身是一个函数,接受源文件作为参数,返回转换结果,这样我们就可以通过require 来加载任何类型的模块或文件。
loader的特性
- Loader 可以通过管道方式链式调用,每个 loader 可以把资源转换成任意格式并传递给下一个 loader ,但是最后一个 loader 必须返回 JavaScript。
- Loader 可以同步或异步执行。
- Loader 运行在 node.js 环境中,所以可以做任何可能的事情。
- Loader 可以接受参数,以此来传递配置项给 loader。
- Loader 可以通过文件扩展名(或正则表达式)绑定给不同类型的文件。
- Loader 可以通过 npm 发布和安装。
- 除了通过 package.json 的 main 指定,通常的模块也可以导出一个 loader 来使用。
- Loader 可以访问配置。
- 插件可以让 loader 拥有更多特性。
- Loader 可以分发出附加的任意文件。
Loader 本身也是运行在 node.js 环境中的 JavaScript 模块,它通常会返回一个函数。大多数情况下,我们通过 npm 来管理 loader,但是你也可以在项目中自己写 loader 模块。
按照惯例,而非必须,loader 一般以 xxx-loader 的方式命名,xxx 代表了这个 loader 要做的转换功能,比如 json-loader。
在引用 loader 的时候可以使用全名 json-loader,或者使用短名 json。这个命名规则和搜索优先级顺序在 webpack 的 resolveLoader.moduleTemplates api 中定义。
Default: ["*-webpack-loader", "*-web-loader", "*-loader", "*"]
Loader 可以在 require() 引用模块的时候添加,也可以在 webpack 全局配置中进行绑定,还可以通过命令行的方式使用。
接上一节的例子,我们要在页面中引入一个 CSS 文件 style.css,首页将 style.css 也看成是一个模块,然后用 css-loader 来读取它,再用 style-loader 把它插入到页面中。
/* style.css */
body { background: yellow; }
require("!style-loader!css-loader!./style.css") // 载入 style.css
document.write('It works.')
document.write(require('./module.js'))
安装loader
npm install css-loader style-loader
如果每次 require CSS 文件的时候都要写 loader 前缀,是一件很繁琐的事情。我们可以根据模块类型(扩展名)来自动绑定需要的 loader。
将 entry.js 中的 require(“!style!css!./style.css”) 修改为 require(“./style.css”) ,然后执行:
$ webpack entry.js bundle.js --module-bind 'css=style-loader!css-loader'
# 有些环境下可能需要使用双引号
$ webpack entry.js bundle.js --module-bind "css=style-loader!css-loader"
配置文件(重点)
Webpack 在执行的时候,除了在命令行传入参数,还可以通过指定的配置文件来执行。默认情况下,会搜索当前目录的 webpack.config.js 文件,这个文件是一个 node.js 模块,返回一个 json 格式的配置信息对象,或者通过 –config 选项来指定配置文件。
在根目录创建 package.json 来添加 webpack 需要的依赖:
{
"name": "webpack-example",
"version": "1.0.0",
"description": "A simple webpack example.",
"main": "bundle.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"webpack"
],
"author": "zhaoda",
"license": "MIT",
"devDependencies": {
"css-loader": "^0.21.0",
"style-loader": "^0.13.0",
"webpack": "^1.12.2"
}
}
# 如果没有写入权限,请尝试如下代码更改权限
chflags -R nouchg .
sudo chmod 775 package.json
别忘了运行 npm install
然后创建一个配置文件 webpack.config.js
var webpack = require('webpack')
module.exports = {
entry: './entry.js',
output: {
path: __dirname,
filename: 'bundle.js'
},
module: {
loaders: [
{test: /\.css$/, loader: 'style-loader!css-loader'}
]
}
}
同时简化 entry.js 中的 style.css 加载方式:
require('./style.css')
最后运行 webpack,可以看到 webpack 通过配置文件执行的结果和上一章节通过命令行 webpack entry.js bundle.js –module-bind ‘css=style-loader!css-loader’ 执行的结果是一样的。
插件
插件可以完成更多 loader 不能完成的功能。
插件的使用一般是在 webpack 的配置信息 plugins 选项中指定。
Webpack 本身内置了一些常用的插件,还可以通过 npm 安装第三方插件。
接下来,我们利用一个最简单的 BannerPlugin 内置插件来实践插件的配置和运行,这个插件的作用是给输出的文件头部添加注释信息。
修改 webpack.config.js,添加 plugins:
var webpack = require('webpack')
module.exports = {
entry: './entry.js',
output: {
path: __dirname,
filename: 'bundle.js'
},
module: {
loaders: [
{test: /\.css$/, loader: 'style-loader!css-loader'}
]
},
plugins: [
new webpack.BannerPlugin('This file is created by zhaoda')
]
}
然后运行 webpack,打开 bundle.js,可以看到文件头部出现了我们指定的注释信息:
/*! This file is created by zhaoda */
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
// 后面代码省略
本人刚接触这块东西,有不对的地方还望指正