写在前面:

文章翻译自petehunt大神的petehunt/webpack-howto,作为学习webpack的开始。fork了一份,翻译后的在这里https://github.com/zjzhome/webpack-howto/blob/master/README-cn.md,有些地方翻译的不好,也希望在阅读后对于不好的地方对出评论或者在github上提个issue。


本文目标

本文讲述如何使用webpack将事情做好,包括了我们在Instagram做的大多数事情,我们没做的当然没有:)

我的建议:以此文作为学习webpack的开始,然后再阅读官方的文档说明。

预备知识

  • 要了解browserify,RequireJS或者其他类似的东东
  • 了解以下事情的价值:
    • 模块划分
    • 异步加载
    • 打包静态资源,比如图片和CSS

1、为什么使用webpack

  • 和browserify类似,但可以将你的app划分为不同的文件。 如果你的单页应用你有多个页面,用户只需下载当前页的代码,如果他们离开此页浏览其他页面,不用再次下载那些通用的代码。

  • 通常情况下可以替代grunt和gulp,因为webpack可以构建和打包CSS,预处理CSS、可以编译为JS的语言和图片等等。

webpack支持AMD和CommonJS以及其他的模块系统(Angular、ES6)。如果你不知道用哪种,使用CommonJS。

2、对于使用Browserify的童鞋

下面的两个命令是等价的:

browserify main.js > bundle.js
webpack main.js bundle.js

不过,webpack比browserify更加给力,一般情况下,我们会创建webpack.config.js来保证条理性。

// webpack.config.js
module.exports = {
entry: './main.js',
output: {
filename: 'bundle.js'
}
};

这完全是我们熟悉的JS,所以随意将挥洒你的代码。

3、如果调用webpack

切换到包含webpack.config.js的目录, 运行:

  • webpack  构建一次,开发环境下使用
  • webpack -p  构建一次,生产环境使用(压缩)
  • webpack --watch  持续构建生产环境下使用(构建速度快)
  • webpack -d  生成sourcemap

4、可编译为JS的语言

webpack中和browserify转换器以及RequireJS中的插件等价的是loader。下面展示了如何让webpack支持加载CoffeeScript和Facebook JSX+ES6(你需要首先 npm install babel-loader coffee-loader )):

// webpack.config.js
module.exports = {
entry: './main.js',
output: {
filename: 'bundle.js'
},
module: {
loaders: [
{ test: /\.coffee$/, loader: 'coffee-loader' },
{ test: /\.js$/, loader: 'babel-loader' }
]
}
};

为了在加载文件的时候不必生命文件扩展名,你必须加上 resolve.extensions 这个参数来告诉webpack该寻找哪些文件.

// webpack.config.js
module.exports = {
entry: './main.js',
output: {
filename: 'bundle.js'
},
module: {
loaders: [
{ test: /\.coffee$/, loader: 'coffee-loader' },
{ test: /\.js$/, loader: 'babel-loader' }
]
},
resolve: {
// you can now require('file') instead of require('file.coffee')
extensions: ['', '.js', '.json', '.coffee']
}
};

5、样式和图片

首先,在你的代码中使用require()来引入你的静态资源。

require('./bootstrap.css');
require('./myapp.less'); var img = document.createElement('img');
img.src = require('./glyph.png');

当你引入CSS(或者less等),webpack会将CSS作为字符串打包到JS中,然后 require() 会在页面中插入 <style> 标签。当引入图片资源的时候,webpack会将图片地址打包进JS, require() 返回图片地址。

但是你要告诉webpack怎么做:

// webpack.config.js
module.exports = {
entry: './main.js',
output: {
path: './build', // This is where images AND js will go
publicPath: 'http://mycdn.com/', // This is used to generate URLs to e.g. images
filename: 'bundle.js'
},
module: {
loaders: [
{ test: /\.less$/, loader: 'style-loader!css-loader!less-loader' }, // use ! to chain loaders
{ test: /\.css$/, loader: 'style-loader!css-loader' },
{test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192'} // inline base64 URLs for <=8k images, direct URLs for the rest
]
}
};

6、特征标识

有些代码我们只想用在开发环境(比如日志)或者内部的服务器(比如处于内测的未发布产品特性)。在你的代码里,使用以下几个变量:

if (__DEV__) {
console.warn('Extra logging');
}
// ...
if (__PRERELEASE__) {
showSecretFeature();
}

然后告诉webpack这些全局变量:

// webpack.config.js

// definePlugin takes raw strings and inserts them, so you can put strings of JS if you want.
var definePlugin = new webpack.DefinePlugin({
__DEV__: JSON.stringify(JSON.parse(process.env.BUILD_DEV || 'true')),
__PRERELEASE__: JSON.stringify(JSON.parse(process.env.BUILD_PRERELEASE || 'false'))
}); module.exports = {
entry: './main.js',
output: {
filename: 'bundle.js'
},
plugins: [definePlugin]
};

然后你可以在命令行里使用BUILD_DEV=1 BUILD_PRERELEASE=1 webpack命令构建,不过注意因为webpack -p命令会去清除无用的代码,所有抱在这些代码块里的代码都会被删除,所以不要泄露私密特性或字符串。

7、多入口

假设你有一个用户资料页面和一个订阅页面,用户在浏览资料页面的你不想用户下载订阅页面的代码。所以要打多个包,为每一个页面创建一个“主要模块”(也叫作入口):

// webpack.config.js
module.exports = {
entry: {
Profile: './profile.js',
Feed: './feed.js'
},
output: {
path: 'build',
filename: '[name].js' // Template based on keys in entry above
}
};

对于资料页,在页面插入 <script src="build/Profile.js"></script> ,订阅页面也是一样。

8、优化通用代码

订阅页面和资料页面共用许多代码(像React以及其他的样式和组件等)。webpack可以抽出他们共用的代码,然后打一个通用包在各个页面缓存。

// webpack.config.js

var webpack = require('webpack');

var commonsPlugin =
new webpack.optimize.CommonsChunkPlugin('common.js'); module.exports = {
entry: {
Profile: './profile.js',
Feed: './feed.js'
},
output: {
path: 'build',
filename: '[name].js' // Template based on keys in entry above
},
plugins: [commonsPlugin]
};

在上一步的script标签之前加上 <script src="build/common.js"></script> ,然后尽情享受免费的高速缓存吧。

9、异步加载

CommonJS是同步的,但是Webpack提供一个方法来异步的指定依赖。这在客户端路由中很有用,每个页面都需要路由,你不想直到你真正需要他们的时候才下载相关功能。

指定你想异步加载的分割点,比如:

if (window.location.pathname === '/feed') {
showLoadingState();
require.ensure([], function() { // this syntax is weird but it works
hideLoadingState();
require('./feed').show(); // when this function is called, the module is guaranteed to be synchronously available.
});
} else if (window.location.pathname === '/profile') {
showLoadingState();
require.ensure([], function() {
hideLoadingState();
require('./profile').show();
});
}

webpack会做接下来的工作,并且产生额外的块文件,然后加载他们。

当你加载这些文件到html的script标签,webpack假定他们在根目录,你可以通过 output.publicPath 来定义:

// webpack.config.js
output: {
path: "/home/proj/public/assets", //path to where webpack will build your stuff
publicPath: "/assets/" //path that will be considered when requiring your files
}

其他资源

看一下真实的案例:一个成功的团队是如何使用webpack的。这是Pete Hunt在全球开源大会上关于Intagram使用的webpack的讨论:http://youtu.be/VkTCL6Nqm6Y

FAQ

webpack看起来不是模块化的

webpack是严格模块化的。和browserify和requirejs等替代选择工具相比,webpack的伟大之处在于在构建过程中他让插件将自己注入到尽可能多的地方。webpack很多看似内建的功能只是默认加载的插件,他们是可以重写的(比如CommonJS的require()语法分析器)。

[译]开始学习webpack的更多相关文章

  1. 深入学习webpack(一)

    深入学习webpack(一) 模块化的相关库和工具已经很多了,包括require.js.sea.js和一些工程化工具webpack.gulp.grant.那么我们该如何选择呢? 其实,我们只需要掌握了 ...

  2. (译) 强化学习 第一部分:Q-Learning 以及相关探索

    (译) 强化学习 第一部分:Q-Learning 以及相关探索 Q-Learning review: Q-Learning 的基础要点是:有一个关于环境状态S的表达式,这些状态中可能的动作 a,然后你 ...

  3. webpack4 学习 --- webpack和webpack-dev-server

    以前了解过webpack2, 所以对webpack 不是很陌生,就直接入主题吧.新建一个文件夹,就叫它webpack-tut吧.然后在文件中新建一个src 文件夹,存放我们的源文件,再在src 文件夹 ...

  4. 如何学习 Webpack

    webpack-howto Tip: 本文是 webpack-howto 的原文,我觉得这篇文章写得非常好,确实算是目前学习 webpack 入门的必读文章.直接收录之. 本教程的目标 这是一本教你如 ...

  5. 深入学习webpack(二)

    深入学习webpack(二) 在深入学习webpack(一)中,我通过一个例子介绍了webpack的基本使用方法,下面将更为系统的学习webpack的基本概念,对于一门技术的掌握我认为系统化还是很重要 ...

  6. 跟我一起学习webpack使用配置文件(二)

    接着跟我一起学习webpack(一)中的项目来,我们接下来使用配置文件 使用npx webpack -h 我们可以查看webpack的配置参数 从我们在package.json中添加的命令来看,当项目 ...

  7. 学习webpack基础笔记01

    学习webpack基础笔记 1.webpack搭建环境最重要的就是如何使用loader和plugins,使用yarn/npm安装插件.预处理器,正确的配置好去使用 2.从0配置webpack - 1. ...

  8. vue第二单元(webpack的配置-学习webpack的常用配置)

    第二单元(webpack的配置-学习webpack的常用配置) #课程目标 掌握webpack的常用配置 掌握如何根据实际的需求修改webpack的对应配置 了解webpack-dev-server的 ...

  9. 零基础学习webpack打包管理

    这些天在项目之余的时间学习了webpack打包项目的东西,非常荣幸的找到一些大神的文章来学习,死劲嚼了几天,终于略知一二.在以后的工作上还需继续学习,下面我将分享我这几天学到的一点东西,希望能让我一个 ...

随机推荐

  1. 如何实现一个c/s模式的flv视频点播系统

    一.写在前面 视频点播,是一个曾经很热,现如今依然很热的一项视频服务技术.本人最近致力于研究将各种视频格式应用于点播系统中,现已研究成功FLV, F4V, MP4, TS格式的视频点播解决方案,完全支 ...

  2. 在C++中使用golang的协程

    开源项目cpp_features提供了一个仿golang协程的stackful协程库. 可以在c++中使用golang的协程,大概语法是这样的: #include <iostream> v ...

  3. boost.asio源码剖析

    一. 前 言二. 架构浅析三. 流程分析     * 常见流程分析之一(Tcp异步连接)      * 常见流程分析之二(Tcp异步接受连接)      * 常见流程分析之三(Tcp异步读写数据)   ...

  4. 【译文】漫谈ASP.NET中的Session

    最近这两天被一个Web Farm环境下的Session处理问题虐得很痛苦,网上到处找解决方案,在无意中翻看到这篇文章,感觉很不错,顺手查了一下,貌似没有现成的译文,于是一咬牙一跺脚把这篇文章翻译出来了 ...

  5. DQS安装失败——系统重新引导是否处于挂起状态

    问题:         安装完SQL Server 2012后,准备安装DQS服务,但是总是提示:操作"检查系统重新引导是否处于挂起状态"已完成,但有错误,正在中止安装.非常无奈, ...

  6. IFormatProvider,ICustomFormatter,IFormattable总结

    IFormatProvider中 public object GetFormat(Type formatType); 该方法主要用于获取一个 ICustomFormatter接口的实例 ICustom ...

  7. Design Mode 之 创建模式

    A.创建模式 首先,简单工厂模式不属于24种涉及模式. A0.简单工厂模式 简单工厂模式,分为三种:普通简单工厂.多方法简单工厂.静态方法简单工厂. A01.普通 就是建立一个工厂类,对实现了同一接口 ...

  8. Coin Test

    描述 As is known to all,if you throw a coin up and let it droped on the desk there are usually three r ...

  9. 1.4.9 DocValues

    DocValues 在solr4.2以后,引入了一个令人兴奋的功能,这个功能在lucene存在已经一段时间了,但是还没有在solr中使用. 在某些方面,DocValue 是一种非常有效的索引方式. 为 ...

  10. mina 字节数组编解码器的写法 II

    I 里面的写法不够严谨,这也是我之前说它简陋的主要原因,下面来个更加严谨.完整一点儿的: ByteArrayEncoder.java package org.bruce.mina.cpp.codec; ...