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. 通过button提交表单

    通过 input button 而不是input submit提交. <!DOCTYPE html> <html lang="en"> <head&g ...

  2. android弹出式菜单、弹出式对话框、弹出式窗口

    http://www.open-open.com/lib/view/open1389767042601.html http://www.open-open.com/lib/view/open13321 ...

  3. ural 1192 Ball in a Dream

    #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> # ...

  4. /usr/lib64/python2.6/site-packages/pycurl.so: undefined symbol: CRYPTO_set_locking_callback

    [root@frontend01 yum.repos.d]# cd /etc/yum.repos.d;wget http://rpms.adiscon.com/v8-stable/rsyslog.re ...

  5. HDOJ 1418 抱歉(欧拉公式)

    Problem Description 非常抱歉,本来兴冲冲地搞一场练习赛,由于我准备不足,出现很多数据的错误,现在这里换一个简单的题目: 前几天在网上查找ACM资料的时候,看到一个中学的奥数题目,就 ...

  6. HDOJ 1163 Eddy's digital Roots(九余数定理的应用)

    Problem Description The digital root of a positive integer is found by summing the digits of the int ...

  7. 深入理解C#第二版笔记

    基础知识 委托 如果代码想要执行操作,但不知道操作细节,一般可以使用委托.例如:Thread类之所以知道要在一个新线程里运行什么,唯一的原因就是在启动新线程时,向它提供了一个ThreadStart委托 ...

  8. 【KMP】剪花布条

    KMP算法 又水了一题.算是巩固复习吧. Problem Description 一块花布条,里面有些图案,另有一块直接可用的小饰条,里面也有一些图案.对于给定的花布条和小饰条,计算一下能从花布条中尽 ...

  9. Java中静态数据的初始化顺序

    Java的类中的数据成员中包含有静态成员(static)时,静态数据成员的初始化顺序是怎样的呢? [程序实例1] import java.util.*; import java.lang.*; imp ...

  10. Oracle_Q&A_02

    Step02: Import SQL FILE Step02: QUESTION & ANSWER --1查询员工姓名和职位字数相等的员工 --2查询e_name以s结尾的员工(不用like) ...