写在前面:

文章翻译自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. Control.Refresh Control.Invalidate 和 Control.OnPaint之间的联系和区别

    1.Control.Invalidate会放一个WM_PAINT消息到消息队列,当Control处理到该消息的时候,就调用OnPaint. 2.Control.Refresh相当于以下两行:Contr ...

  2. 关于Android使TextView可以滚动的设置

    添加一行代码…… textView.setMovementMethod(ScrollingMovementMethod.getInstance());

  3. 小白日记50:kali渗透测试之Web渗透-CSRF

    CSRF CSRF原理:经常与XSS混淆. 从信任的角度进行区分:XSS:利用用户对站点的信任:CSRF:利用站点对已经身份认证的信任(有一定的信任)[默认情况:站点不信任客户端] 结合社工在身份认证 ...

  4. docker 连接容器

    1.通过端口映射 sudo docker run -d -P training/webapp python app.py 容器有一个内部网络和IP地址(在使用Docker部分我们使用docker in ...

  5. sublime自己常用到的设置

    一.快捷“在浏览器打开” 在首选项->按键绑定-用户中添加代码: { "keys": ["f12"], "command": &quo ...

  6. Solr的检索运算符 (转载)

    1. “:” 指定字段查指定值,如返回所有值*:*2. “?” 表示单个任意字符的通配3. “*” 表示多个任意字符的通配(不能在检索的项开始使用*或者?符号)4. “~” 表示模糊检索,如检索拼写类 ...

  7. C#三大支柱之多态

    1.包含与委托---has-a 2.嵌套类型(枚举.类.接口.结构等) 由于只有嵌套类才可声明为私有,通过嵌套类则可以完全控制内部类型的访问级别. 嵌套类型是包含类的成员,所有可以访问包含类的私有成员 ...

  8. 怒刷DP之 HDU 1024

    Max Sum Plus Plus Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u S ...

  9. 改变WPF ListBoxItem的选中样式

    想用ListBox作一个类似IOS 设置的菜单,却发现很难改变ListBoxItem鼠标移过.选中的默认蓝色背景与边框. 尝试使用Style来设置strigger,依然不成功.在百度搜索一些资料,提到 ...

  10. [转]如何下载tizen源码(图文教程)?

    http://blog.csdn.net/flydream0/article/details/8996654 当前tizen发布的最新源码版本是2.1,本文将以图文教程讲述如何下载tizen源码,关于 ...