webpack简明使用教程

webpack简明使用教程

试想一下,你有entry.js和add.js文件,然后需要在entry.js中使用add.js中的功能,有人可能会说,直接把add.js中的代码复制到entry.js中不就OK了吗,确实,这样可以达到效果,但是如果还有anotherEntry.js文件需要add.js中的功能呢,明显这样做的结果是导致了大量的代码重复,违背了前端模块化的思想,有人又说了,可以用AMD规范(RequireJs),这个是一个好的解决方法,但是过于复杂,于是webpack运应而生了,webpack,是一种模块打包工具,它可以把多个模块打包成一个完整的模块,因此,webpack也是前端模块化的一种解决方案,你只需要提供一个入口文件,webpack自动帮你把这个入口文件需要的各种依赖包含进来,并生成一个输出文件,我们在html页面中使用的就是这个文件,webpack能处理的模块类型也更为广泛,js,css,sass,es6,图片等等。总之,webpack能把模块1,模块2,模块3...模块n打包成一个js模块(也就是一个js文件),其中模块1可以是一个js文件,模块2可以是一个css文件,模块3可以是一副图片等等,请看下图:


下面全面介绍一下webpack的使用:

一、准备阶段-----安装

我为本文写了一个示例库,webpack-demos,请先安装这个库:

git clone mbjgithub (汪汪) · GitHub

如果没有安装git,请先安装git,Git - Downloads

如果没有全局安装webpack,为了能使用webpack命令,请先全局安装webpack,npm install webpack -g,如果这样安装不了,或者很长时间也没有安装好,请用cnpm install webpack -g,这样一分钟内就可以安装好,如果不知道cnpm是什么,或者在安装cnpm的过程中出现了问题,请参考我的这篇文章,安装webpack缓慢的解决方法

然后进入webpack-demos目录。

二、webpack的使用

1、demo01---------webpack最简单使用

首先进入demo01目录,输入npm install,这样npm会自动读取package.json中内容,给我们安装项目的依赖包,然后执行命令webpack,这样你会发现在public下面多了一个bundle.js文件,在浏览器中打开index.html可以看到效果,index.html中引用的就是webpack打包生成的bundle.js文件。

下面我们来重新走一遍这个流程,自己亲手试试:

(1)demo01项目,切换到demo01目录,然后执行npm init 命令,执行这个命令会让你回答一些问题,不过这些问题你现在全部按enter就行了,然后你会发现demo01中多了一个package.json文件,这个文件时npm标准说明文件,npm可以根据这个文件下载项目的依赖包。然后执行cnpm install --save-dev webpack,在该项目中安装webpack。至于为什么要加--save-dev参数请看安装webpack缓慢的解决方法

(2)新建app和public文件夹,app中放置我们写的模块,public放置webpack打包生成的模块,然后新建webpack.config.js文件,运行webpack命令时会自动读取该文件,然后在app文件夹中新建entry.js和greet.js,在public中新建index.html。

greet.js中的代码

function greet(){
	var divEle=document.createElement("div");
	divEle.innerHTML="hello,webpack";
    return divEle;
}
module.exports=greet;

entry.js中的代码

var greet=require("./greet.js");
document.getElementById("container").appendChild(greet());

index.html中的代码

<!DOCTYPE html>
<html>
 <head>
  <meta charset="utf-8">
  <title></title>
 </head>
 <body>
  <div id="container"></div>
  <script type="text/javascript" rel="stylesheet" src="./bundle.js"></script>
 </body>
</html>

webpack.config.js中的代码

module.exports={
	entry:__dirname+"/app/entry.js",   //入口文件
	output:{                           
		path:__dirname+"/public",      //输出文件的存放位置
		filename:"bundle.js"           //输出文件的名称
	} 
}

entry指明的是webpack的入口文件,webpack会把这个文件包含的所有模块打包到一个模块中,output指明了打包完成后,这个输出模块的存放位置和文件名。

(3)执行webpack命令,在public下会发现生成了一个bundle.js文件,你可以运行一下index.html,然后查看一下bundle.js。是不是很激动,webpack实现了前端的模块化,你已经成功的将复杂的js拆分为简单的js文件,如果不使用webpack的话,恐怕greet.js中的代码要写在entry.js中。

2、demo02--------webpack最重要的功能,loader的使用

Loaders是webpack中最让人激动人心的功能之一了。通过使用不同的loader,webpack通过调用外部的脚本或工具可以对各种各样的格式的文件进行处理,比如说分析JSON文件并把它转换为JavaScript文件,或者说把下一代的JS文件(ES6,ES7)转换为现代浏览器可以识别的JS文件。或者说对React的开发而言,合适的Loaders可以把React的JSX文件转换为JS文件。

Loaders需要单独安装并且需要在webpack.config.js下的modules关键字下进行配置,Loaders的配置选项包括以下几方面:

  • test:一个匹配loaders所处理的文件的拓展名的正则表达式(必须)
  • loader:loader的名称(必须)
  • include/exclude:手动添加必须处理的文件(文件夹)或屏蔽不需要处理的文件(文件夹)(可选);
  • query:为loaders提供额外的设置选项(可选)
  • 进入demo02文件夹,安装依赖,cnpm install --save-dev webpack,然后看webpack.config.js中的代码:

    module.exports={
    	entry:__dirname+"/app/entry.js",   //入口文件
    	output:{                           
    		path:__dirname+"/public",      //输出文件的存放位置
    		filename:"bundle.js"           //输出文件的名称
    	},
    	module:{
    		loaders:[
    		 {
    	                test:/\.json$/,   //正则表达式,告诉loader应该加载以.json结尾的文件
    		 	loader:"json"
    		 }
    		]
    	} 
    }
    

    和demo01的webpack.config.js相比多了一个module配置,loaders是数组,表明可以使用多个loader,上面的loader是一个json-loader,可以用来处理以.json结尾的文件,通过这个json-loader,才使得入口文件可以像require js文件一样,require json文件。不过首先得安装json-loader,输入cnpm install -save-dev json-loader即可安装,

    下面重新梳理一下整个流程,自己在走一遍:

    (1)新建demo02文件夹,输入npm init命令,生成package.json文件,输入

    cnpm install --save-dev webpack,安装webpack依赖,由于我们要用到json-loader,因此输入cnpm install --save-dev json-loader。

    (2)在demo02下,新建app和public文件夹,新建webpack.config.js,在app下,新建config.json,entry.js,greet.js文件,在public下新建index.html文件,

    config.json中代码

    {
    	"content":"hello,webpack"
    }

    greet.js中代码

    var config=require("./config.json");
    function greet(){
    	var divEle=document.createElement("div");
    	// divEle.innerHTML="hello,webpack";
    	divEle.innerHTML=config.content;
        return divEle;
    }
    module.exports=greet;

    entry.js中代码

    var greet=require("./greet.js");
    document.getElementById("container").appendChild(greet());

    index.html中代码

    <!DOCTYPE html>
    <html>
     <head>
      <meta charset="utf-8">
      <title></title>
     </head>
     <body>
      <div id="container"></div>
      <script type="text/javascript" rel="stylesheet" src="./bundle.js"></script>
     </body>
    </html>

    webpack.config.js中代码

    module.exports={
    	entry:__dirname+"/app/entry.js",   //入口文件
    	output:{                           
    		path:__dirname+"/public",      //输出文件的存放位置
    		filename:"bundle.js"           //输出文件的名称
    	},
    	module:{
    		loaders:[
    		 {
    		 	test:/\.json$/,   //正则表达式,告诉loader应该加载以.json结尾的文件
    		 	loader:"json"
    		 }
    		]
    	} 
    }
    

    (3)运行webpack命令,可以看到public文件夹下多了一个bundle.js文件。这说明webpack成功把config.js,greet.js,entry.js打包成了bundle.js ,

    3、demo03--------webpack的style-loader和css-loader的使用

    style-loder和css-loader得一起使用才能把css文件也打包到bundle.js文件中,和json-loader差不多,只不过style-loader和css-loader处理的是css文件罢了。下面我i就不具体演示了,详情请看demo03,你可以直接cnpm install,这样会下载好整个项目的依赖包。然后需要注意一点的是用css-loader和style-loader的时候,有时候会报错,报错的最可能的原因就是npm或者cnpm在下载css-loader和style-loader的时候缺胳膊少腿,少下了一下模块,解决的方法就是先卸载css-loader和style-loader然后在重新下载,或者直接重新下载缺少的模块。

    4、demo04-----------webpack插件的使用

    插件不同与loader,loader时作用于一类文件,而插件是作用于整个项目,比如BannerPlugin,这个插件的功能就是给输出的bundle.js加上版权声明,CommonsChunkPlugin插件是提取依赖的公共部分,全部插件,请看webpack list of plugins

    请看demo04的webpack.config.js代码

    var webpack=require("webpack");

    module.exports={
    	entry:__dirname+"/app/entry.js",   //入口文件
    	output:{                           
    		path:__dirname+"/public",      //输出文件的存放位置
    		filename:"bundle.js"           //输出文件的名称
    	},
    	module:{
    		loaders:[
    		 {
    		 	test:/\.json$/,   //正则表达式,告诉loader应该加载以.json结尾的文件
    		 	loader:"json"
    		 },
    		 {
    		 	test:/\.css$/,
    		 	loader:"style!css"  //对css的处理需要style和css两个loader来处理,!用于连接两个loader
    		 }
    		]
    	},
    	plugins:[
    	 new webpack.BannerPlugin("CopyRight wangwang 2016-10")  //这个插件的作用是给output的文件添加版权声明
    	] 
    
    }
    

    你可以在bundle.js中看到效果。这里我还做了一点改动,请看package.json中代码

    {
      "name": "demo01",
      "version": "1.0.0",
      "description": "",
      "main": "webpack.config.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1",
        "start":"webpack"  
      },
      "author": "wangwang",
      "license": "ISC",
      "devDependencies": {
        "css-loader": "^0.25.0",
        "json-loader": "^0.5.4",
        "style-loader": "^0.13.1",
        "webpack": "^1.13.3"
      }
    }

    注意上面的script属性,我添加了"start":"webpack"这里的意思就是让npm start命令等价于webpack命令,这样,只需要输入npm start就相当于执行webpack命令了。

    5、demo05--------webpack多入口文件和CommonsChunkPlugin插件

    请看webpack.config.js文件代码

    var webpack=require("webpack");
    
    var path=require("path");
    
    module.exports={
    	entry:{
    		pageA:__dirname+"/app/pageA.js",   //入口文件pageA
    		pageB:__dirname+"/app/pageB.js"    //入口文件pageB
    	},
    	output:{
    		path:path.join(__dirname,"public"), //输出文件目录
    		filename:"[name].bundle.js",        //[name]引用entry的pageA或者pageB属性
    		chunkFilename:"[id].chunk.js"
    	},
    	plugins:[
    	 new webpack.optimize.CommonsChunkPlugin({
    	 	filename:"commons.js",  //这个插件用于提取多个入口文件共享的模块,并输出到commons.js中,实现模块复用
    	 	name:"commons"
    	 }),
    	 new webpack.optimize.UglifyJsPlugin()
    	]
    }
    

    demo05的效果时在public下会生成pageA.bundle.js,pageB.bundle.js和commons.js文件,commons.js文件中包含入口文件pageA.js和pageB.js都使用的模块,这是CommonsChunkPlugin插件的功劳。

    三、总结

    webpack确实一个很好用的模块化打包工具,小项目其实没有什么感觉,但是到了大项目,webpack的优势就越来越明显了。由于篇幅限制,webpack的很多功能都没有一一列出,比如,压缩,分离css,js等等,想要继续深入了解的请看webpack官网


    四、gulp使用教程(看到别人写的已经很好了,就不自己写了)

    一点 | gulp详细入门教程

    编辑于 2017-02-08 19:02