译webpack之谜
Posted 前端乖乖
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了译webpack之谜相关的知识,希望对你有一定的参考价值。
本文译自【Webpack-The Confusing Parts】 https://medium.com/@rajaraodv/webpack-the-confusing-parts-58712f8fcad9#.m63u83at2
前言
webpack
是当前最受欢迎的模块管理器(module bundler
),对于使用React
开发的项目来说堪称神器。当然,对于使用其他框架,比如Angular
或者Backbone
等的开发者来说,webpack
也是种很好的工具。
第一次配置webpack.config.js
时,有很多地方使我很困惑。在使用了webpack
一段时间后,我认识到正是这些地方让webpack
如此强大和迷人。
webpack
核心理念
一切都是模块。—— 在
webpack
中,不仅js
文件可以作为一个模块,其他文件(css
,images
,html
)都可以作为模块。这就是说,你可以在其他文件中加载这些模块,require('myJSfile.js')
,或者require('myCSSfile.css')
。这意味着我们将任意文件拆分成便于管理的小文件,然后通过在其他文件中加载这些小文件来达到重复利用的目的。按需加载(
Load only "what" you need and "when" you need
)—— 一般情况下打包工具会将我们所有的模块打包生成一个最终的文件bundle.js
。但是在实际应用中,bundle.js
通常会很大(10M~15M),需要很长时间才能加载完成。webpack
提供了多种code splitting
的方法,会生成过个打包后的文件,且支持按需加载。这样我们只有在需要用到某个模块的时候才会异步加载该模块。
现在我们来看下这些令人困惑的部分。
开发环境和生产环境(Development Vs Production)
首先要明确的一点是,webpack
有很多特性,有些只在开发环境使用,还有些只在生产环境使用,当然还有在生产环境和开发环境都可以使用的。如下图所示:
所以通常我们会有两个
config
文件,以针对开发环境和生产环境作不同配置。
在package.json
做如下配置:
webpack CLI
Vs webpack-dev-server
需要知道webpack
提供了两个接口
webpack
命令行工具(webpack CLI tool
) —— 默认使用这种方式,无需单独安装,被集成在webpack
中。webpack-dev-server
——node.js
服务器,需要单独安装
Webpack CLI (适用于生产环境构建)
可以通过命令行添加参数,也可以通过配置文件(默认为webpack.config.js
),webpack
打包时会读取这些配置。
最初学习
webpack
时你可能用的就是命令行方式,之后大部分使用命令行的场景为生产环境打包。
使用方法
webpack-dev-server
(适用于开发环境构建)
webpack-dev-server
是一个基于Express
的node
服务器,默认使用8080
端口。这个方式的优点是它提供了浏览器热加载(Hot Module Replacement
)。
使用方法
webpack
和webpack-dev-server
选项
需要注意的一点是,像inline
和hot
这些选项,只有webpack-dev-server
有;而另一些比如hide-modules
是单独为webpack
命令行方式提供的选项。
webpack-dev-server
参数
为webpack-dev-server
提供参数有两种方式。
通过
webpack.config.js
中的devServer
通过
CLI
选项
使用方法
我发现通过
devServer
设置的配置项(hot: true, inline: true
)有时不起作用。所以我更喜欢使用CLI
的方式,在package.json
中添加如下代码:
注意
不要
同时设置devServer
中hot: true
和CLI
中--hot
"hot"
Vs "inline"
inline
模式会触发页面的动态重载(live reloading
);hot
模式会触发页面的热加载(hot Module Replacement
),这种模式只重载页面中变化了的部分。如果同时设置了inline
和hot
,webpack-dev-server
会先尝试HMR
,如果HMR
失败了,则重载整个页面。
entry
(String
Vs Array
Vs Object
)
entry
指出了打包入口文件,支持字符串
,数组
和对象
三种形式。这三种形式有何区别呢?
如果为单一入口文件,也就是说入口文件只有一个,那这三种方式会得到相同的结果。
entry
— Array
若有多个入口文件,且彼此独立,那么可以使用数组方式。比如入口文件为a.js
,b.js
,使用数组方式会将b.js
的内容追加到bundle.js
的内容后。
一个很常见的场景就是在html
文件加入统计代码,比如googleAnalytics.js
,就可以用数组的方式告知webpack
将其打包到bundle.js
末尾,如下:
entry
— Object
这种方式主要针对多页面应用(指包含多个html
文件)。这种方式可以使webpack
根据这个对象一次就打包出多个文件。
如下这种配置可以打包出两个js
文件:indexEntry.js
和profileEntry.js
,可以分别在index.html
和profile.html
中引入。
使用方法
注: output
中name
对应的是entry
中的属性名。
entry
— 结合使用array
和object
可以在object
内部再使用array
方式。比如如下配置:
output
— path
和publicPath
output
设定了打包生成文件的路径。它有两个属性path
和publicPath
。path
告知webpack
将打包生成后的文件存储于什么路径,比如我们希望将文件打包到dist
文件夹下,只需设置path
为/dist
即可;publicPath
用于在生产环境打包时更新文件(包括css
、html
)中的url
。
如下配置:
举个例子,在你的css
文件中,用到了./test.png
这个url
去加载本地的图片。但是在生产环境中,这张图片test.png
会存储在cdn
服务器上。这样如果还是用./test.png
就会访问不到该图片,必须把文件中所有的url
手动改成cdn
的路径才能在生产环境使用。
webpack
为我们提供的publicPath
这个属性使我们可以很方便地处理这类问题。只需要将publicPath
设置为生产环境的路径,这些识别publicPath
的插件,比如url-loader
,就会自动为我们处理好url
。如下图所示:
(译者注:
publicPath
还用于指定在使用webpack-dev-server
时,如何访问其暂存于内存中的打包后的文件。)
加载器和链式加载器(Loaders And Chaining Loaders
)
加载器是一些node
模块,可以加载(load
)或者引入(import
)各种类型的文件使其转化成浏览器支持的文件格式,包括js
,css
等等。
比如:可以使用babel-loader
将使用ES6
写的js
文件转换为浏览器支持的ES5
格式。如下:
链式加载(从右至左)
对同一种类型的文件可以链式运用多个加载器。链式调用为从右向左,通过!
分割加载器。
举例:我们有一个css
文件myCSSFile.css
,我们想将这个文件中的内容转换成<style>CSS content</style>
的形式插入到我们的html
页面中。可以使用两个加载器css-loader
和style-loader
来达成以上目的:
如下展示了其原理:
1、webpack
查找模块中依赖的css
文件。也就是说,webpack
会检查js
文件中是否引用了myCSSFile.css
。如果找到了依赖,webpack
会先用css-loader
对其进行处理。
2、css-loader
会加载所有的css
和这个css
的依赖(比如@import otherCSS
),并将css
的内容处理为JSON
数据格式。然后将结果传给style-loader
进行处理。
3、style-loader
会对接收到的json
数据进行处理,并将其处理为style
标签——<style>CSS contents</style>
,然后插入到html
页面中。
加载器可配置
可以向loaders
传递各种参数进行配置。
在以下这个例子中,我们对url-loader
进行了配置:小于1024字节的图片将会被转为为base64
格式,而大于1024字节的图片还是使用图片url
。有两种方式进行配置:
.babelrc
文件
使用babel-loader
的话,需要配置presets
才能正确转化,包括将es6
转换为es5
,将JSX
转为js
。可以通过如下方式设置参数
但是在很多项目中babel
的配置可能会比较大,所以可以单独在babel
的配置文件.babelrc
中配置。如果有.babelrc
,babel-loader
会自动加载该文件。
如下:
插件(Plugins
)
插件是一些node
模块,可以对生成的打包文件进行处理。
比如,uglifyJSPlugin
插件可以对打包后得到的bundle.js
进行压缩处理,减小文件体积。extract-text-webpack-plugin
运用了css-loader
和style-loader
将所有的css
统一处理并根据结果生成一个单独的css
文件(style.css
),将文件链接插入到html
文件中。
注:
如果你只是想使用内联css
样式,在html
页面中加入style
标签,可以只用css
和style
加载器。如下:
加载器和插件(Loaders Vs Plugins
)
可以看到,加载器作用于单独的文件,在bundle
生成之前完成;
插件作用于bundle
或chunk
,通常是在bundle
生成过程的最后进行。一些插件比如commonsChunksPlugins
甚至会影响bundle
如何生成。(译者注
:该插件用于提取出各个模块中引用的相同模块,下篇文章code splitting
中会详细说明)
文件后缀处理(Resolving File Extensions
)
很多webpack
配置文件中都包含一个resolve extensions
的属性,其中包含一个空字符串。这个空字符串就是用于正确加载不含后缀的文件的。比如:require('./myJSFile')
或 import myJSFile from './myJSFile'
。
注: 翻译水平有限,如有问题还希望大家能不吝赐教,希望和大家共同进步。
前端圈--打造专业的前端技术会议
为web前端开发者提供技术分享和交流的平台
打造一个良好的前端圈生态,推动web标准化的发展
官网:http://fequan.com
投稿:content@fequan.com
赞助合作:apply@fequan.com
以上是关于译webpack之谜的主要内容,如果未能解决你的问题,请参考以下文章