Webpack: 为Web开发而生的模块管理器

原文地址:http://hanjianwei.com/2014/09/10/webpack-package-manager-for-web/

10 Sep 2014

对于开发人员而言,好的包管理器可以让工作事半功倍。现在流行的编程语言大多有自己的包管理系统。近年来,Web开发越来越火,其开发工具也随之越来越好用了,而Webpack就是一款专为Web开发设计的包管理器。它能够很好地管理、打包Web开发中所用到的HTML、Javascript、CSS以及各种静态文件(图片、字体等),让开发过程更加高效。

模块化编程

长久以来,Web开发者都是把所需Javascript、CSS文件一股脑放进HTML里面,对于庞大的项目来说管理起来非常麻烦。Node.js的出现改变了这种状态,虽然Javascript的模块并非Node.js发明,但确实是它把这个概念发扬光大了。

但Node.js毕竟是用于服务端的,为了将模块化技术用于浏览器,人们又造出了一大堆工具:RequireJSBrowserifyLABjsSea.jsDuo等。同时,由于Javascript的标准没有对模块的规范进行定义,人们又定义了一系列不同的模块定义:CommonJSAMDCMDUMD等。这真是一件令人悲伤的事情,希望ES6 Module的出现能中止这种分裂的状态。

Webpack同时支持CommonJS和AMD形式的模块,对于不支持的模块格式,还支持对模块进行shimming。举个简单的例子:

// content.js
module.exports = "It works from content.js.";
// entry.js
document.write(require("./content.js"));
<!-- index.html -->
<html>
  <head>
    <meta charset="utf-8">
  </head>
  <body>
    <script type="text/javascript" src="bundle.js" charset="utf-8"></script>
  </body>
</html>

这里entry.js是入口文件,它加载了content.js。通过命令行对entry.js进行编译:

$ webpack ./entry.js bundle.js

打开index.html就会看到content.js中的内容已经被加载进来了。

Web开发中用到的不但有Javascript,还有CSS以及各种静态文件。Webpack定义了一种叫加载器loader的东西,它能够把各种资源文件进行转换,用正确的格式加载到浏览器中。比如对于上述程序,如果我们有一个对应的CSS文件:

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

我们修改一下entry.js来加载该CSS:

require("!style!css!./style.css");
document.write(require("./content.js"));

然后再重新编译、打开index.html就可以看到CSS加载进来了。执行上述程序前我们必须安装所需的loader:

npm install --save-dev style-loader css-loader

在编译时,css-loader会读取CSS文件,并处理其中的import,返回CSS代码;而style-loader会将返回的CSS代码作为DOM的style。如果你用的是SASS,只要把require语句改成require("!style!css!sass!./style.scss")就可以了。

Webpack提供了很多常见的loader,开发的时候可以把用到的文件都require进来,生成一个单一的Javascript,便于发布。

上述require CSS的代码虽然功能强大,但写起来比较繁琐,Webpack支持在配置文件中进行配置,把符合条件的文件用同一组loader来进行处理。下面是我用的一组loader:

{
  module: {
    loaders: [
      {test: /\.coffee$/, loader: 'coffee'},
      {test: /\.html$/,   loader: 'html'},
      {test: /\.json$/,   loader: 'json'},
      {test: /\.css$/,    loader: 'style!css!autoprefixer'},
      {test: /\.scss$/,   loader: 'style!css!autoprefixer!sass'},
      {test: /\.woff$/,   loader: "url?limit=10000&minetype=application/font-woff"},
      {test: /\.ttf$/,    loader: "file"},
      {test: /\.eot$/,    loader: "file"},
      {test: /\.svg$/,    loader: "file"}
    ]
  }
}

有了上述配置,直接require('./style.css')就可以了,系统会自动先执行autoprefixer,然后加载CSS,然后再加载为DOM的style。

此外,Webpack还支持插件,实现对Javascript的压缩、替换等各种操作。

依赖模块的管理

Webpack自己并不提供模块的下载,但它可以和已有的包管理器很好的配合。你可以用npmBowercomponent等来管理你的Web开发资源,同时在Webpack中加载它们。

Webpack的文件加载分为三种:

  • 绝对路径,比如require('/home/me/file')。此时会首先检查目标是否为目录,如果是目录则检查package.jsonmain字段(你可以让Webpack同时检查Bower的字段);如果没有package.json或者没有main字段,则会用index作为文件名。经过上述过程,我们解析到一个绝对路径的文件名,然后会尝试为其加上扩展名(扩展名可在webpack.config.js中设置),第一个存在的文件作为最终的结果。
  • 相对路径,比如require('./file')。使用当前路径或配置文件中的context作为相对路径的目录。加载过程和绝对路径相似。
  • 模块路径,如require('module/lib/file')。会在配置文件中的所有查找目录中查找。

对于复杂的模块路径,还可以设置别名。一个路径解析配置的例子:

{
  resolve: {
    root: [appRoot, nodeRoot, bowerRoot],
    modulesDirectories: [appModuleRoot],
    alias: {
      'angular': 'angular/angular',
      'lodash': 'lodash/dist/lodash'
    },
    extensions: ['', '.js', '.coffee', '.html', '.css', '.scss']
  }
}

工具的集成

Webpack能够和gruntgulpkarma等已有工具很好地集成。

此外,除了输出单一文件,Webpack还支持代码分割多入口以及运行时模块替换,是非常值得Web开发者关注的一个工具。

最后附上我的配置文件:

// webpack.config.js
var path = require('path');
var webpack = require('webpack');

var appRoot = path.join(__dirname, 'app');
var appModuleRoot = path.join(__dirname, 'app/components');
var bowerRoot = path.join(__dirname, 'bower_components');
var nodeRoot = path.join(__dirname, 'node_modules');

module.exports = {
  entry: 'app',
  output: {
    path: path.resolve('./app/assets'),
    filename: 'bundle.js',
    publicPath: '/assets/'
  },
  resolve: {
    root: [appRoot, nodeRoot, bowerRoot],
    modulesDirectories: [appModuleRoot],
    alias: {
      'angular-ui-tree': 'angular-ui-tree/dist/',
      'angular-date-range-picker': 'angular-date-range-picker/build/'
    },
    extensions: ['', '.js', '.coffee', '.html', '.css', '.scss']
  },
  resolveLoader: {
    root: nodeRoot
  },
  plugins: [
    new webpack.ProvidePlugin({
      _: 'lodash'
    }),
    new webpack.ResolverPlugin([
      new webpack.ResolverPlugin.DirectoryDescriptionFilePlugin("bower.json", ["main"])
    ])
  ],
  module: {
    loaders: [
      {test: /\.coffee$/, loader: 'coffee'},
      {test: /\.html$/,   loader: 'html'},
      {test: /\.json$/,   loader: 'json'},
      {test: /\.css$/,    loader: 'style!css!autoprefixer'},
      {test: /\.scss$/,   loader: 'style!css!autoprefixer!sass'},
      {test: /\.woff$/,   loader: "url?limit=10000&minetype=application/font-woff"},
      {test: /\.ttf$/,    loader: "file"},
      {test: /\.eot$/,    loader: "file"},
      {test: /\.svg$/,    loader: "file"}
    ]
  }
};

Webpack: 为Web开发而生的模块管理器[转]的更多相关文章

  1. [Web 前端] 使用yarn代替npm作为node.js的模块管理器

    cp from : https://www.jianshu.com/p/bfe96f89da0e     Fast, reliable, and secure dependency managemen ...

  2. 【Java Web开发学习】Spring MVC 拦截器HandlerInterceptor

    [Java Web开发学习]Spring MVC 拦截器HandlerInterceptor 转载:https://www.cnblogs.com/yangchongxing/p/9324119.ht ...

  3. nodejs-npm模块管理器

    JavaScript 标准参考教程(alpha) 草稿二:Node.js npm模块管理器 GitHub TOP npm模块管理器 来自<JavaScript 标准参考教程(alpha)> ...

  4. 使用yarn代替npm作为node.js的模块管理器

    使用yarn代替npm作为node.js的模块管理器 转 https://www.jianshu.com/p/bfe96f89da0e     Fast, reliable, and secure d ...

  5. JS模块规范 前端模块管理器

    一:JS模块规范(为了将js文件像java类一样被import和使用而定义为模块, 组织js文件,实现良好的文件层次结构.调用结构) A:CommonJS就是为JS的表现来制定规范,因为js没有模块的 ...

  6. npm模块管理器

    npm模块管理器 地址: http://javascript.ruanyifeng.com/nodejs/npm.html#

  7. npm模块管理器入门

    什么是 NPM npm 是 Node 官方提供的包管理工具,他已经成了 Node 包的标准发布平台,用于 Node 包的发布.传播.依赖控制.npm 提供了命令行工具,使你可以方便地下载.安装.升级. ...

  8. 安卓开发:UI组件-布局管理器和文本显示

    接下来的随笔,记录了在学习b站up主:天哥在奔跑,录制的教学视频的同时,进行一个app开发. up主:天哥在奔跑 视频地址:https://www.bilibili.com/video/av38409 ...

  9. SpringBoot整合WEB开发--(七)注册拦截器

    1.创建一个拦截器类实现HandlerInterceptor接口,重写其中的3个方法,这拦截器中方法的执行顺序为:preHandle--Controller--postHandle--afterCom ...

随机推荐

  1. 学习python的记录

    今天买了本head first pyhton,目的用于更加方便的学习自动化,希望可以坚持下来,没看完一张,在博客园里做出笔记 环境:公司或家中的windows7  python3.6版本 书籍:hea ...

  2. android EditText内嵌图片

    如下所示: 主要用到的属性:android:drawableLeft <EditText android:layout_width="match_parent" androi ...

  3. Visual Studio 2015 Owin+MVC+WebAPI+ODataV4+EntityFrawork+Identity+Oauth2.0+AngularJS 1.x 学习笔记

    2016年,.net 会有很多大更新 ASP.NET 5 在此之前我都是用着古老的.net做开发的 (WebForm + IIS) 为了接下来应对 .net 的新功能,我特地去学习了一下基本的 MVC ...

  4. C51系列RAM寄存器表

    特殊功能寄存器地址表 SFR 符号 字节 地址 位地址和位名称 D7 D6 D5 D4 D3 D2 D1 D0 P0口 P0 80H P0.7 P0.6 P0.5 P0.4 P0.3 P0.2 P0. ...

  5. QT 让窗口(或控件)居中

    代码如下: XXX::XXX(QWidget *parent /* = 0 */) { .................. //注意,resize一定要放在这段代码的前面 resize(300, 3 ...

  6. logstash multiline

    filter { multiline { pattern => "^\s+%{TIMESTAMP_ISO8601}" negate=>true what=>&qu ...

  7. 虚拟机LUN扩大后,重新分区

    [root@ywcrmdb ~]# fdisk -l Disk /dev/sda: 751.6 GB, 751619276800 bytes 255 heads, 63 sectors/track, ...

  8. 切割 bitmap

    最近在安卓手机控制蓝牙打印机打印图片,有时候图片太大,考虑到bitmap的切割,在此,献上代码,各位小主指点 public class ImageSplitter { public static Ar ...

  9. Android中ListView异步加载数据

    1.主Activity public class MainActivity extends Activity { private ListView listView; private ArrayLis ...

  10. 从此走上一条iOS程序猿不归路。。。

    新的城市,新的生活!前不久刚刚结束了苦逼的面试找工作之旅,期间也小有收货,如今正处年底工作闲暇之余,将前一阵子陆陆续续的总结整理了一下,本人菜鸟程序猿一只,水平有限,本文总结的知识不算深入,比较浅显, ...