写在前面:

文章翻译自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. linux 认证方式

  2. iOS开发——实战OC篇&环境搭建之StoryBoard(玩转UINavigationController与UITabBarController)

      环境搭建之StoryBoard(玩转UINavigationController与UITabBarController)   研究了这么就IOS开发,都没有所处一个像样或者自己忙一点的项目.最近自 ...

  3. UVA 1069 - Always an integer(数论)

    1069 - Always an integer 题意:给定一个多项式,推断是否总是整数 思路:LRJ大白上的例题,上面给出了证明,仅仅要1到k + 1(k为最高次数)带入方程都是整数,那么整个方程就 ...

  4. Linux TCP队列相关参数的总结 转

        在Linux上做网络应用的性能优化时,一般都会对TCP相关的内核参数进行调节,特别是和缓冲.队列有关的参数.网上搜到的文章会告诉你需要修改哪些参数,但我们经常是知其然而不知其所以然,每次照抄过 ...

  5. nexus-2.13.0-01.war

    https://sonatype-download.global.ssl.fastly.net/nexus/oss/nexus-2.13.0-01.war

  6. ubantu 安装mysql

    sudo apt-get install mysql-server mysql-client

  7. php 运行客户提交代码(攻击)和运行图片中的代码

    1.$a=@strrev(ecalper_gerp);$b=@strrev(edoced_46esab);@$a($b(L3h4L2Ug),$_POST[POST],bxxb); 2.<?php ...

  8. 向linux内核版本号添加字符/为何有时会自动添加“+”号

    转载:http://blog.csdn.net/adaptiver/article/details/7225980 1.   引子 编译2.6.35.7 kernel版本的时候发现,“2.6.35.7 ...

  9. Redis缓存异常的容错实现方法( .net)

    using DotNet.Log; /// <summary> /// Redis缓存辅助类 /// /// 修改纪录 /// /// 2015-10-26 版本:1.0 SongBiao ...

  10. 【Shell脚本学习18】Shell for循环

    与其他编程语言类似,Shell支持for循环. for循环一般格式为: for 变量 in 列表 do command1 command2 ... commandN done 列表是一组值(数字.字符 ...