Webpack 是当下最热门的前端资源模块化管理和打包工具。它能够将很多松散的模块依照依赖和规则打包成符合生产环境部署的前端资源。

通过 loader 的转换,不论什么形式的资源都能够视作模块,比方 CommonJs 模块、 AMD 模块、 ES6 模块、CSS、图片、 JSON、Coffeescript、 LESS 等。

一.安装

能够通过npm来安装,全局安装:

$ npm install -g webpack
项目根文件夹下安装。通过cmd环境进入到项目根文件夹下:

$ npm install --save-dev webpack

(注)此时在项目根文件夹会出现一个package.json文件


二.配置文件

在项目根文件夹下新增一个webpack.config.js文件。内容例如以下:

var webpack = require('webpack');
module.exports = {
	//根文件夹
	context: __dirname + "",
	//文件入口
	entry: {
		index: './js/main.js',
		other: './js/other.js'
	},
	//文件出口
	output: {
		path: __dirname + "/dist", // 设置输出文件夹
		filename: '[name].bundle.js', // 输出文件名称
	},
	module: {
		//载入器配置
		loaders: [
			//.css文件使用 style-loader 和 css-loader 来处理
			//【$ npm install css-loader style-loader --save-dev】命令行表示初始化style-loader, css-loader
			{ test: /\.css$/, loader: "style!css" },
			//图片文件使用 url-loader来处理,小于8kb的直接转为base64 
			//【$ npm install url-loader --save-dev】
			//【$ npm install file-loader --save-dev】
			{ test: /\.(jpeg|png|gif|svg)$/i, loader: 'url-loader?limit=8192&name=[name].[ext]' },
			//字体文件使用 url-loader来处理。小于8kb的直接转为base64 
			//{ test: /\.(woff|woff2|eot|ttf|otf)$/i, loader: 'url-loader?limit=8192&name=[name].[ext]' },
			//.js文件使用 babel-loader 来处理
			//【$ npm install babel-loader】
			//{ test: /\.js$/, loader: 'babel-loader' , exclude: /node_modules/},
			//.scss 文件使用 style-loader、css-loader 和 sass-loader 来处理
			//{ test: /\.js?$/, loaders: ['react-hot-loader', 'babel-loader'], exclude: /node_modules/ },
			//{ test: /\.scss$/, loader: 'style!css!sass?sourceMap' },
			//.less文件使用 style-loader、css-loader 和 less-loader来处理  
			//{ test: /\.less$/, loader: "style!css!less" },
			//.jsx文件使用 babel-loader来处理  
			//{ test: /\.jsx$/, loader: ['babel-loader'] , exclude: /(node_modules|bower_components)/}
			//【$ npm install --save-dev react-hot-loader】
			//【$ npm install --save-dev webpack-dev-server】
			//【$ npm install less --save-dev】命令行表示初始化less
			//【$ npm install css-loader style-loader --save-dev】命令行表示初始化style-loader, css-loader
			//【$ npm install less less-loader --save-dev】命令行表示初始化less-loader, 基于style-loader,css-loader
		]
	},
	// 插件
	plugins: [
		// 默认会把全部入口节点的公共代码提取出来,生成一个common.js
		new webpack.optimize.CommonsChunkPlugin('common'),
		// 压缩代码抬头凝视
		new webpack.BannerPlugin('此处加入打包抬头凝视!'),
		// 代码压缩
		new webpack.optimize.UglifyJsPlugin({
			compress: {
				warnings: false
			}
		})
	],
	//其他解决方式配置
	resolve: {
		// 配置简写,配置过后。书写该文件路径的时候能够省略文件后缀。如require("common")
		extensions: ['.js', '.jsx', '.coffee']
	},
	//因为压缩后的代码不易于定位错误,配置该项后错误发生时就可以採用source-map的形式直接显示你出错代码的位置。

devtool: 'eval-source-map' }

该文件中已经做了相关凝视,主要想说的一点是文件入口entry配置。假设你仅仅有一个文件入口。则直接用

entry: "./js/main.js"
本例中我使用了两个文件入口文件。各自是main.js和other.js。这里项目已经搭建完毕,项目总体文件夹结构例如以下:

(注)libs文件夹下的文件自行搜索就可以找到


三.代码模块

此例中新建了2个模块,各自是MyFunction.js和MyObject.js这两个文件代码例如以下:

MyFunction.js:

var content = new Object();
content.showContent = function() {
	console.log("This is my Function!");
}
exports = module.exports = content;
MyObject.js:
function content() {
	var showContent = function() {
		console.log("This is my Object!");
	}

	var object = new Object();
	object.showContent = showContent;
	return object;
}
exports = module.exports = content;
(注)这两个模块代码也展示了两种不同创建模块js写法的规范
此时编辑主程main.js文件:

$(document).ready(function() {
	console.log("Test Start---------------------");
	async.auto({
		//运行代码  [创建型对象]
		t1: function(callback) {
			var MyObject = require("./core/MyObject.js");
			var myObject = new MyObject();
			myObject.showContent();
			callback(null);
		},
		//运行代码  [方法型对象]
		t2: function(callback) {
			var MyFunction = require("./core/MyFunction.js");
			MyFunction.showContent();
			callback(null);
		},
		//运行代码  [图片型对象]
		t3: function(callback) {
			$("#img").attr("src", "./js/assets/img.png");
			callback(null);
		},
		//运行代码  [解析JSON数据]
		t4: function(callback) {
			$.getJSON("./js/assets/data.json", function(data) {
				console.log("this is type of " + typeof data);
				callback(null);
			});
		},
		//运行代码  [AJAX请求同域数据]
		t5: ["t4", function(callback, results) {
			$.ajax({
				url: "./js/assets/data.txt",
				async: false,
				error: function(response, state) {
					console.log("ajax_error:" + response);
					callback(null);
				},
				success: function(response, state) {
					console.log("ajax_ok:" + response);
					callback(null);
				}
			});
		}],
		access: ["t1", "t2", "t3", "t4", "t5",
			function(callback, results) {
				callback(null);
			}
		]
	}, function(error, results) {
		console.log("Test End-----------------------");
	});
});
该主程文件用到了async异步运行。这样就能够更清晰的看到打印结果。


四.打包展示

在cmd环境下进入到你的项目根文件夹。运行打包命令:

$ webpack -d

(注)webpack还有其它的一些打包和编译命令,能够自己搜索一下,此处不再介绍

打包成功后的显演示样例如以下:

此时会在项目根文件夹下新增了一个dist文件夹。里面有三个文件,分别为common.bundle.js、index.bundle.js和other.bundle.js,当中common.bundle.js表示两入口文件共同拥有模块,我们如今仅仅測当中一个入口文件就可以,在index.html将打包文件引入就可以展示运行代码。

<!DOCTYPE html>
<html>

	<head>
		<meta charset="utf-8" />
		<title></title>
		<script src="js/libs/async.js"></script>
		<script src="js/libs/jquery-1.8.0.min.js"></script>
		<script src="dist/common.bundle.js"></script>
		<script src="dist/index.bundle.js"></script>
	</head>

	<body>
		<img id="img" />
	</body>

</html>
运行结果:

要记住一点,Webpack尽管都支持CommonJS规范和AMD规范。可是终于的主程序是打包到同一个bundle.js文件里,这就意味着bundle.js文件有可能较大。此时若将Webpack应用于浏览器环境而不是服务端环境,因为同步载入原因就有可能引起浏览器载入过程较慢的情况发生。

此时的决策是(1)在webpack.config.js配置项中plugins除去不必要的插件;(2)压缩代码,webpack 自带了一个压缩插件 UglifyJsPlugin,仅仅须要在配置文件里引入就可以。

{
  plugins: [
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false
      }
    })
  ]
}
增加了这个插件之后,编译的速度会明显变慢,所以一般仅仅在生产环境启用。


模块化规范

在描写叙述Webpack中有说到,它都支持CommonJS规范和AMD规范,在Web前端中,模块化规范主要有3种,各自是CommonJS规范、AMD规范和CMD规范,而后两种规范都是在CommonJS规范的基础上发展而来。

CommonJS规范

commonJS规范基本的标志是定义了require和exports或module.exports的写法实现代码模块化管理。

CommonJS是在浏览器环境之外构建JavaScript生态系统为目标产生的项目。比方server和桌面环境中。CommonJS规范是为了解决JavaScript的作用域问题而定义的模块形式,能够使每一个模块在它自身的命名空间中运行。该规范的主要内容是:模块必须通过  module.exports导出对外的变量或接口。通过require()来导入其它模块的输出到当前模块。写法例如以下:

// moduleA.js  
module.exports = function( value ){  
    return value * 2;  
}  

// moduleB.js  
var multiplyBy2 = require('./moduleA');  
var result = multiplyBy2(4);  
CommonJS是同步载入模块。 server端的Node.js遵循CommonJS规范。核心思想是同意模块通过require 方法来同步载入所要依赖的其它模块。然后通过 exports或module.exports来导出须要暴露的接口。

能够说当初定义CommonJS规范的主要目的是应用在服务端。

(注)应用实现如Node.js

AMD规范

AMD规范是在CommonJS规范的基础上应用而来,由于CommonJS规范是同步运行,不利于在浏览器上运行,所以AMD规范应运而生。AMD规范的主要标志是定义了define写法,是异步载入模块。AMD规范事实上仅仅有一个主要接口 define(id,dependencies,factory),它要在声明模块的时候指定全部的依赖dependencies。而且还要当做形參传到factory中,对于依赖的模块提前运行,依赖前置。

define("module", ["dep1", "dep2"], function(d1, d2) {  
  return someExportedValue;  
});  
require(["module"], function(module) { /* ... */ });  
(注)应用实现如require.js框架

CMD规范

CMD规范与AMD规范差点儿一样,唯一不同的是在定义模块时不须要知道其依赖条件。即无依赖前置一说。在须要调用其它模块时直接require进来就能够使用,即遵循就近依赖。延时运行的原则。

define(function(require, exports, module) {  
  var $ = require('jquery');  
  var Spinning = require('./spinning');  
  exports.doSomething = ...  
  module.exports = ...  
})  

(注)应用实现如seajs.js框架

RequireJS 想成为浏览器端的模块载入器,同一时候也想成为 Rhino / Node 等环境的模块载入器。

SeaJS 则专注于 Web 浏览器端,同一时候通过 Node 扩展的方式能够非常方便跑在 Node server端。据统计。针对模块化框架的使用情况。国外较喜欢使用AMD规范,而国内则较多使用CMD规范,毕竟CMD规范是从国内发展而来。


实例Demo:http://download.csdn.net/detail/zeping891103/9796332