本文译自Webpack — The Confusing Parts,原文需翻墙。

Webpack现在是React应用程序标配的模块打包器,我估计Angular2和其他框架的用户也在大规模使用。我第一次看到Webpack配置文件的时候,感觉实在太陌生,太混乱了。在玩了一段时间后,我现在觉得是Webpack独特的语法和新的理念导致了初学阶段的复杂度。顺便说一下,也正是因为这些理念,才让Webpack如此受欢迎。

正因为Webpack入门容易让人困惑,所以我写了这篇文章,希望能够帮助其他人更轻松的入门,用起来更顺手。这是第一部分。

Webpack的核心理念

Webpack的两个核心理念是:

  1. 万物皆模块:就像JS文件可以当做模块,那么其他所有的文件(CSS,图片,HTML)都可以当做模块。这样,就可以require(“myJSfile.js”)或者require(“myCSSfile.css”)。这意味着,我们可以对模块再进行细分,分割成更小更容易管理的粒度,实现复用等等。
  2. 按需加载,异步加载:一般的模块打包器会打包所有的模块然后生成一个巨大的输出文件bundle.js。但是在许多实际应用的APP中,这个bundle.js可能会有10MB-15MB那么大,并且总是会加载!而Webpack有一些功能可以分割代码然后生成多个"bundle"文件并且可以在你需要的时候异步加载。

1.开发模式 VS 生产模式

首先要注意的事情是Webpack有太多的功能,有些只有开发模式下可以用,有些只有生产模式下可以用,还有一些开发模式和生产模式下都可以用。

一般情况下,大部分项目都会用到许多功能,所以通常有两个大型的Webpack配置文件。

执行打包的话可以像下面这样在package.json中写脚本:

“scripts”: {
//npm run build 生产模式打包
“build”: “webpack --config webpack.config.prod.js”, //npm run dev 开发模式打包并且运行dev-server
“dev”: “webpack-dev-server”
}

  

2.Webpack CLI VS webpack-dev-server

需要强调的一点是Webpack这个模块打包器提供了两个接口:

  1. Webpack CLI工具-默认接口(作为Webpack的一部分自动安装)。
  2. webpack-dev-server工具-一个Node.js服务器(需要单独安装)。

Webpack CLI(适用于生产模式的构建)

此工具可以通过CLI或者配置文件(默认值:webpack.config.js)获取配置并传递给Webpack进行打包。

初学Webpack的时候可以使用CLI,大部分可能只会用来进行生产模式的构建。

用法:

//用法1:

//全局安装
npm install webpack-dev-server --g //在终端中运行
$ webpack-dev-server --inline --hot //用法2: //写到package.json的脚本里
“scripts”: {
“start”: “webpack-dev-server --inline --hot”,
...
} //运行脚本
$ npm start //打开浏览器
http://localhost:8080

  

Webpack VS webpack-dev-server 选项

值得注意的是,有些选项,例如"inline"和"hot"是webpack-dev-server独有的选项,还有一些选项像是"hide-modules"是CLI独有的选项。

webpack-dev-server CLI 选项 VS config 选项

还有一点要注意的是,有两种方式向webpack-dev-server传递选项:

  1. 通过webpack.config.js里的"devServer"对象。
  2. 通过CLI选项。
//通过 CLI
webpack-dev-server --hot --inline //通过 webpack.config.js
devServer: {
inline: true,
hot:true
}

  我发现有时候通过devServer配置(hot: true和inline: true)不起作用,所以最好还是把命令写到package.json里,通过CLI传递选项。

//package.json
{
scripts:
{“start”: “webpack-dev-server --hot --inline”}
}

  

注意:确保没有同时传递hot: true和--hot。

“hot” VS “inline” webpack-dev-server 选项

"inline"选项为整个页面添加了"Live Reloading"功能,而"hot"选项开启了"Hot Module Reloading"功能,这样就会尝试着重载发生变化的组件,而不是整个页面。

//当源码改变时,下面三种命令都会导致重新打包,但是

//1. 不会重载浏览器中的页面
$ webpack-dev-server //2. 会重载整个页面
$ webpack-dev-server --inline //3. reloads just the module(HMR), or the entire page if HMR fails
//3. 重载改变的模块(HMR),如果HMR失败的话就重载整个页面
$ webpack-dev-server --inline --hot

  

3."entry"-String VS Array VS Object

Entry的作用是告诉Webpack根模块,或者说起点在哪。值可以是String,Array或者Object。这里可能会让你困惑,但是不同的类型有各自的用武之地。

如果只有一个entry(大部分APP都是),可以选择任何格式,结果都是一样的。

entry-Array

如果你想添加多个文件并且这些文件不会互相依赖的话,可以使用Array格式。 例如:你可能想在HTML中放入"googleAnalytics.js",可以像下图这样把它添加到到bundle.js的结尾

entry-Object

现在,假设你有一个真正的多页应用,而不是一个多页面的SPA。有多个HTML文件(index.html和profile.html)。然后可以通过对象形式的entry来让Webpack一次性生成多个包

下面的配置会生成两个JS文件,indexEntry.js和profileEntry.js,可以分别在indexEntry.html和profileEntry.html中使用。

用法:
//profile.html
<script src=”dist/profileEntry.js”></script>
//index.html
<script src=”dist/indexEntry.js”></script>

  注意:文件名来自"entry"对象的键名。

entry-组合

可以在entry对象中使用数组形式的entry,举个例子,下面的配置会生成三个文件:一个包含有三个库文件的vendoe.js,一个index.js和一个profile.js。

4.output — "path" Vs "publicPath"

output的作用是告诉Webpack如何存储生成的结果文件,其中path和publicPath这两个属性可能会让人困惑。

path仅仅用来告诉Webpack在哪里存放结果文件,而publicPath被一些Webpack插件用来处理CSS,HTML文件中的URL,一般用于生产模式。

例如,CSS里,可能会用./test.png这样的url来加载本地图片,但是在生产模式中,"test.png"这种图片可能是放在CDN上的,服务器是跑在云平台上的。这就意味着,生产模式中,你不得不手动处理文件里的URL保证它们指向的是CDN地址。

现在,你可以用Webpack的publicPath和一些具有publicPath检测功能的插件来自动处理文件中的URL。

// 开发模式:服务器和图片都在本地
.image {
background-image: url(‘./test.png’);
} // 生产模式:服务器跑在云平台上,图片在CDN上
.image {
background-image: url(‘https://someCDN/test.png’);
}

  

Loader 和 Loader链

Loader是用来加载(load)或输入(import)文件的Node模块,不同的loader可以将各种类型的文件转换为浏览器能够接受的格式如JS,Stylesheets等等。更进一步来说,loader允许通过require或ES6的import语句在JS文件中引入各种文件。

例如,可以用babel-loader把ES6语法写的JS转换成浏览器能够兼容的ES5形式:

module: {
loaders: [{
test: /\.js$/, ←检测".js"文件, 通过的话,则使用对应loader
exclude: /node_modules/, ←排除 node_modules 文件夹
loader: ‘babel’ ←使用 babel (‘babel-loader’的简写形式)
}]

  

Loader链(从右向左工作)

多个loader可以链式调用,作用于同一种文件类型。工作链的调用顺序是从右向左,各个loader之间使用"!"分开。

例如,有一个CSS文件myCSSFile.css,我们想把文件里的内容放到HTML文件的标签中。想实现这一点,需要用到两个loader:css-loader和style-loader。

工作流程如下图:

  1. Webpack搜索模块内依赖的CSS文件,通过检查JS文件中是否有require(myCSSFile.css)语句。如果找到了这个依赖文件,Webpack首先把文件传给css-loader。
  2. css-loader载入所有的CSS语句,和CSS文件内的依赖(例如@import otherCSS),处理为JSON,接着Webpack会把这个JSON传给style-loader。
  3. style-loader拿到这个JSON之后会把它放到一个style标签中-,然后把这个style插入index.html文件中。

6.Loader本身也是可以配置的

Loader本身也是可以配置的,传入不同的参数可以实现不同的功能。

在下面的例子中,我们配置url-loader使小于1024字节的图片使用DataURL,大于1024字节的图片使用URL。如下图,有两种方式传入limit参数来实现此功能。

7. .babelrc文件

babel-loader用presets配置将ES6转换为ES5,把React JSX解析为JS。我们可以像下面这样传入query参数来配置:

module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /(node_modules|bower_components)/,
loader: 'babel',
query: {
presets: ['react', 'es2015']
}
}
]
}

  

然而许多项目中babel的配置会很复杂,所以最好把所有的babel-loader配置写在.babelrc文件里。babel-loader会自动加载.babelrc文件如果该文件存在的话。 所以在许多例子中,你会看到下面这种写法:

//webpack.config.js
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /(node_modules|bower_components)/,
loader: 'babel'
}
]
} //.bablerc
{
“presets”: [“react”, “es2015”]
}

  

8.插件

插件是用来处理打包结果的额外模块。

例如,uglifyJSPlugin会对bundle.js进行压缩和混淆处理,可以压缩文件体积。

还有extract-text-webpack-plugin会在内部调用css-loader和style-loader把所有的CSS收集在一起,最后把结果抽取到一个单独的外部styles.css文件并且在index.html中链接styles.css。

//webpack.config.js
//收集所有的.css文件,合并其中的内容并且抽取到一个单独的"styles.css"
var ETP = require("extract-text-webpack-plugin"); module: {
loaders: [
{test: /\.css$/, loader:ETP.extract("style-loader","css-loader") }
]
},
plugins: [
new ExtractTextPlugin("styles.css") //Extract to styles.css file
]
}

  

注意:如果想要把CSS放到HTML的style标签中,可以不使用extract-text-webpack-plugin,只要用css-loader和style-loader就可以了。就像下面这样:

 loaders: [{
test: /\.css$/,
loader: ‘style!css’ <--(style-loader!css-loader的简写形式)
}]

  

9.Loader VS 插件

你可能会意识到,Loader是在打包前或打包的过程中作用于单个文件插件通常在打包过程结束后,作用于包或者chunk级别。还有一些插件例如commonChunksPlugins,更进一步,会修改如何创建包。

10.解析文件扩展名

许多Webpack配置文件都有一个resolve extensions属性,其中包含一个像那面那样的空字符串。这个空字符串是用来帮助解析没有扩展名的文件输入,例如:require('./myJSFile')或者import myJSFile from './myJSFile'。

{
resolve: {
extensions: [‘’, ‘.js’, ‘.jsx’]
}
}
作者:松子
链接:https://zhuanlan.zhihu.com/p/24744677 来自知乎的分享

[翻译]Webpack解惑的更多相关文章

  1. webpack解惑:require的五种用法

    我之前在 <前端搭环境之从入门到放弃>这篇文章中吐槽过,webpack中可以写commonjs格式的require同步语法,可以写AMD格式的require回调语法,还有一个require ...

  2. webpack解惑:多入口文件打包策略

    本文是我用webpack进行项目构建的实践心得,场景是这样的,项目是大型类cms型,技术选型是vue,只支持chrome,有诸多子功能模块,全部打包在一起的话会有好几MB,所以最佳方式是进行多入口打包 ...

  3. webpack解惑:require的五种用法 (转)

    我之前在 <前端搭环境之从入门到放弃>这篇文章中吐槽过,webpack中可以写commonjs格式的require同步语法,可以写AMD格式的require回调语法,还有一个require ...

  4. 前端笔记之Vue(五)TodoList实战&拆分store&跨域&练习代理跨域

    一.TodoList 1.1安装依赖 安装相关依赖: npm install --save-dev webpack npm install --save-dev babel-loader babel- ...

  5. 翻译 | 关键CSS和Webpack: 减少阻塞渲染的CSS的自动化解决方案

    原文地址: Critical CSS and Webpack: Automatically Minimize Render-Blocking CSS 原文作者: Anthony Gore 译者: 蜗牛 ...

  6. 【翻译】Webpack 4 从0配置到生产模式

    查看原文 webpack 4 发布了! webpack 4 作为一个零配置的模块打包器 webpack 是强大的并且有许多独一无二的特点但是有一个痛点就是配置文件. 在中型到大型项目中为webpack ...

  7. 翻译 | 上手 Webpack ? 这篇就够了!

    译者:小 boy (沪江前端开发工程师) 本文原创,转载请注明作者及出处. 原文地址:https://www.smashingmagazine.com/2017/02/a-detailed-intro ...

  8. webpack+react+redux+es6开发模式

    一.预备知识 node, npm, react, redux, es6, webpack 二.学习资源 ECMAScript 6入门 React和Redux的连接react-redux Redux 入 ...

  9. vue+ vue-router + webpack 踩坑之旅

    说是踩坑之旅 其实是最近在思考一些问题 然后想实现方案的时候,就慢慢的查到这些方案   老司机可以忽略下面的内容了 1)起因  考虑到数据分离的问题  因为server是express搭的   自然少 ...

随机推荐

  1. UC编程:环境变量的查询与修改

    每个程序中都维护一个指向环境变量的指针char **environ; 子进程会从父进程继承环境变量.子进程环境变量的修改不一定会影响父进程 无关的多个进程之间修改环境变量不会互相影响 打印环境变量 [ ...

  2. Java集合之LinkedHashSet源码分析

    1.简介 我们知道Set不允许包含相同的元素,如果试图把两个相同元素加入同一个集合中,add方法返回false.根据源码实现中的注释我们可以知道LinkedHashSet是具有可预知迭代顺序的Set接 ...

  3. 使用MySQL Migration Toolkit快速将Oracle数据导入MySQL

    MySQL GUI Tools中的MySQL Migration Toolkit可以非常方便快捷的将Oracle数据导到MySQL中,该软件可以在http://dev.mysql.com/downlo ...

  4. ubuntu下的词典的安装

    因为从事开发,安装一个词典是很有必要,文中介绍安装openyoudao和stardic两个软件的方法 一.openyoudao的安装 因为是由window转来学ubuntu的,所以总是想安装和wind ...

  5. ASP.NET DataTable的操作大全

    DataTable表示一个与内存有关的数据表,可以使用工具栏里面的控件拖放来创建和使用,也可以在编写程序过程中根据需要独立创建和使用,最常见的情况是作为DataSet的成员使用,在这种情况下就需要用在 ...

  6. Linux--安装过程中的根文件系统的分析

    前言: 在这篇文章中S3C6410公版的Linux BSP和U-Boot为了分析,名词和数据文件的所有内容本文是基于环境为例,所有的代码是在设置的示例进行分析的过程中.哈. 假设有不对或者不完好的地方 ...

  7. linux sendmail 邮件服务器架设(fedora 8)

    linux sendmail 邮件服务器架设(fedora 8) 2009-01-22 17:27 3316人阅读 评论(2) 收藏 举报 邮件服务器linuxprotocolscaching测试lo ...

  8. C#/ASP.NET/AJAX

      C#/ASP.NET/AJAX ASP.NET 4.5新特性一:强类型数据绑定(Strongly-Type Data-Bindings) 摘要: 随着ASP.NET 4.5的发布提供了很多的新特性 ...

  9. asp.net mvc放在iis7.5中提示404错误 js异步请求失效解决办法

    asp.net mvc中js发请求一般写成: $.get("/Can/index"本地上是没有问题的但是部署到iis上,提示404,正确的请求的路径是:/网站名/Can/index ...

  10. ACE模板之Jqgrid

    Asp.Net MVC中使用ACE模板之Jqgrid   第一次看到ACE模板,有种感动,有种相见恨晚的感觉,于是迅速来研究.它本身是基于bootstrap和jqueryui,但更nice,整合之后为 ...