webpack学习和简单使用


前言

webpack是一个模块打包器。它将根据模块的依赖关系进行静态分析,然后将这些模块按照指定的规则生成对应的静态资源。

what is webpack

一、webpack安装

首先需要安装NodejsNodejs的具体安装请参考这里Node.js自带了软件包管理器npmWebpack 需要Node.js v0.6以上支持,建议使用最新版Node.js

使用npm命令安装webpack:

npm install webpack -g  

此时Webpack已经安装到了全局环境下,可以通过命令行webpack -h查看是否安装成功。

通常我们会将Webpack安装到项目的依赖中,这样就可以使用项目本地版本的Webpack

# 进入项目目录
# 确定已经有package.json,没有就通过npm init创建
# 安装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 works!')  

然后编译entry.js并打包到bundle.js

webpack entry.js bundle.js  

打包过程会显示日志:

webpack打包过程

用浏览器打开index.html将会看到It works!

接下来添加一个模块module.js文件,并修改入口entry.js

// module.js
module.exports = '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

Webpack会分析入口文件,解析包含依赖关系的各个文件。这些文件(模块)都打包到bundle.jsWebpack会给每个模块分配一个唯一的id并通过这个id索引和访问模块。在页面启动时,会先执行entry.js中的代码,其它模块会在运行require的时候再执行。

三、Loader

Webpack本身只能处理JavaScript模块,如果要处理其他类型的文件,就需要使用loader进行转换。

Loader可以理解为是模块和资源的转换器,它本身是一个函数,接受源文件作为参数,返回转换的结果。这样,我们就可以通过require来加载任何类型的模块或文件,比如CoffeeScriptJSXLESS或图片。

先来看看loader有哪些特性:

  • Loader 可以通过管道方式链式调用,每个loader可以把资源转换成任意格式并传递给下一个loader,但是最后一个loader必须返回JavaScript
  • Loader 可以同步或异步执行。
  • Loader 运行在node.js环境中,所以可以做任何可能的事情。
  • Loader 可以接受参数,以此来传递配置项给loader。
  • Loader 可以通过文件扩展名(或正则表达式)绑定给不同类型的文件。
  • Loader 可以通过npm发布和安装。 除了通过package.jsonmain指定,通常的模块也可以导出一个loader来使用。
  • Loader 可以访问配置。
  • 插件可以让loader拥有更多特性。
  • Loader 可以分发出附加的任意文件。

Loader本身也是运行在node.js环境中的JavaScript模块,它通常会返回一个函数。大多数情况下,我们通过npm来管理loader,但是你也可以在项目中自己写loader模块。

按照惯例,而非必须,loader一般以xxx-loader的方式命名,xxx代表了这个loader要做的转换功能,比如json-loader

在引用loader的时候可以使用全名json-loader,或者使用短名json。这个命名规则和搜索优先级顺序在webpackresolveLoader.moduleTemplatesapi中定义。

Default: ["*-webpack-loader", "*-web-loader", "*-loader", "*"]  

Loader可以在require()引用模块的时候添加,也可以在webpack全局配置中进行绑定,还可以通过命令行的方式使用

接上面的例子,我们要在页面中引入一个CSS文件style.css,首页将style.css也看成是一个模块,然后用css-loader来读取它,再用style-loader把它插入到页面中。

/* style.css */
body {  
    background: yellow;
}

修改entry.js

require("!style!css!./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!css'  

显然,这两种使用loader的方式,效果是一样的。

四、配置文件

Webpack在执行的时候,除了在命令行传入参数,还可以通过指定的配置文件来执行。默认情况下,会搜索当前目录的webpack.config.js文件,这个文件是一个node.js模块,返回一个json格式的配置信息对象,或者通过--config选项来指定配置文件。

继续上面的案例,在根目录创建package.json来添加webpack需要的依赖:

{
  "name": "packtest",
  "version": "1.0.0",
  "description": "A simple webpack example.",
  "main": "bundle.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [
    "webpack"
  ],
  "author": "blinkfox",
  "license": "MIT",
  "devDependencies": {
    "css-loader": "0.21.0",
    "style-loader": "0.13.0",
    "webpack": "1.12.2"
  }
}

别忘了运行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!css'}
    ]
  }
}

同时简化entry.js中的style.css加载方式:

require('./style.css')  

最后运行webpack,可以看到webpack通过配置文件执行的结果和前面通过命令行webpack entry.js bundle.js --module-bind 'css=style!css'执行的结果是一样的。

五、插件

插件可以完成更多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!css" }
        ]
    },
    plugins: [
        new webpack.BannerPlugin('This file is created by blinkfox')
    ]
};

然后运行webpack,打开bundle.js,可以看到文件头部出现了我们指定的注释信息:

/*! This file is created by zhaoda */
/******/ (function(modules) { // webpackBootstrap
/******/  // The module cache
/******/  var installedModules = {};
// 后面代码省略

六、开发环境

当项目逐渐变大,webpack的编译时间会变长,可以通过参数让编译的输出内容带有进度和颜色。

webpack --progress --colors  

如果不想每次修改模块后都重新编译,那么可以启动监听模式。开启监听模式后,没有变化的模块会在编译后缓存到内存中,而不会每次都被重新编译,所以监听模式的整体速度是很快的。

webpack --progress --colors --watch  

当然,使用webpack-dev-server开发服务是一个更好的选择。它将在localhost:8080启动一个express静态资源web服务器,并且会以监听模式自动运行webpack,在浏览器打开http://localhost:8080/http://localhost:8080/webpack-dev-server/可以浏览项目中的页面和编译后的资源输出,并且通过一个socket.io服务实时监听它们的变化并自动刷新页面。

1、安装

npm install webpack-dev-server -g  

2、运行

webpack-dev-server --progress --colors  

七、故障处理

webpack的配置比较复杂,很容出现错误,下面是一些通常的故障处理手段。

一般情况下,webpack如果出问题,会打印一些简单的错误信息,比如模块没有找到。我们还可以通过参数--display-error-details来打印错误详情。

webpack --display-error-details  

webpack的配置提供了resolveresolveLoader参数来设置模块解析的处理细节,resolve用来配置应用层的模块(要被打包的模块)解析,resolveLoader用来配置loader模块的解析。

当引入通过npm安装的node.js模块时,可能出现找不到依赖的错误。Node.js模块的依赖解析算法很简单,是通过查看模块的每一层父目录中的node_modules文件夹来查询依赖的。当出现Node.js模块依赖查找失败的时候,可以尝试设置resolve.fallbackresolveLoader.fallback来解决问题。

module.exports = {  
  resolve: { fallback: path.join(__dirname, "node_modules") },
  resolveLoader: { fallback: path.join(__dirname, "node_modules") }
};

Webpack中涉及路径配置最好使用绝对路径,建议通过 path.resolve(__dirname, "app/folder")path.join(__dirname, "app", "folder")的方式来配置,以兼容Windows环境。

本文参考自:https://www.gitbook.com/book/zhaoda/webpack/details



转载请注明:闪烁之狐 » webpack学习和简单使用

分享到:
主题颜色面板