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. 通知栏快捷按钮自定义教程以及快捷面板提取的思路-转自魔趣论坛-lonyii2

    原帖地址: http://bbs.mfunz.com/forum.php?mod=viewthread&tid=235198&extra=page%3D1%26filter%3Dtyp ...

  2. Altium Designer6打印PCB转印纸设置方法

    在学校经常要用热转印法做一些简单的PCB板,自己用的AD6.6,学校的打印店用99的比较多,这就造成打印不方便.为了充分利用自己实验室的打印机,今天买回来两张PCB打印纸.发现用AD6打印同比例的PC ...

  3. AD 删除一个区域里的所有布线,不删除元器件,丝印等

    想删除一个区域里的所有布线,不删除元器件,丝印等 按F12后输入以下组合:isvia or(istrack and OnTopLayer) or (istrack and OnBottomLayer) ...

  4. ECMAScript 发展历史

    参考文献:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Language_Resources

  5. Linux sar使用

    [root@ywcrmdb ~]# sar -d 1 10 Linux 2.6.32-220.el6.x86_64 (ywcrmdb)  2014年04月19日  _x86_64_ (4 CPU) 1 ...

  6. css属性之box-shadow

    box-shadow 属性向框添加一个或多个阴影. <!DOCTYPE html> <html> <head> <style> div { width: ...

  7. 【转】Linux下tar.xz结尾的文件的解压方法

    原文网址:http://blog.csdn.net/silvervi/article/details/6325698 今天尝试编译内核,下载到了一份tar.xz结尾的压缩文件,网上解决方法比较少,不过 ...

  8. cf509E Pretty Song

    E. Pretty Song time limit per test 1 second memory limit per test 256 megabytes input standard input ...

  9. Misha and Changing Handles

    Description Misha hacked the Codeforces site. Then he decided to let all the users change their hand ...

  10. JS-Math内置对象

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...