[翻译]Webpack解惑
本文译自Webpack — The Confusing Parts,原文需翻墙。
Webpack现在是React应用程序标配的模块打包器,我估计Angular2和其他框架的用户也在大规模使用。我第一次看到Webpack配置文件的时候,感觉实在太陌生,太混乱了。在玩了一段时间后,我现在觉得是Webpack独特的语法和新的理念导致了初学阶段的复杂度。顺便说一下,也正是因为这些理念,才让Webpack如此受欢迎。
正因为Webpack入门容易让人困惑,所以我写了这篇文章,希望能够帮助其他人更轻松的入门,用起来更顺手。这是第一部分。
Webpack的核心理念
Webpack的两个核心理念是:
- 万物皆模块:就像JS文件可以当做模块,那么其他所有的文件(CSS,图片,HTML)都可以当做模块。这样,就可以require(“myJSfile.js”)或者require(“myCSSfile.css”)。这意味着,我们可以对模块再进行细分,分割成更小更容易管理的粒度,实现复用等等。
- 按需加载,异步加载:一般的模块打包器会打包所有的模块然后生成一个巨大的输出文件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这个模块打包器提供了两个接口:
- Webpack CLI工具-默认接口(作为Webpack的一部分自动安装)。
- 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传递选项:
- 通过webpack.config.js里的"devServer"对象。
- 通过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。
工作流程如下图:
- Webpack搜索模块内依赖的CSS文件,通过检查JS文件中是否有require(myCSSFile.css)语句。如果找到了这个依赖文件,Webpack首先把文件传给css-loader。
- css-loader载入所有的CSS语句,和CSS文件内的依赖(例如@import otherCSS),处理为JSON,接着Webpack会把这个JSON传给style-loader。
- 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解惑的更多相关文章
- webpack解惑:require的五种用法
我之前在 <前端搭环境之从入门到放弃>这篇文章中吐槽过,webpack中可以写commonjs格式的require同步语法,可以写AMD格式的require回调语法,还有一个require ...
- webpack解惑:多入口文件打包策略
本文是我用webpack进行项目构建的实践心得,场景是这样的,项目是大型类cms型,技术选型是vue,只支持chrome,有诸多子功能模块,全部打包在一起的话会有好几MB,所以最佳方式是进行多入口打包 ...
- webpack解惑:require的五种用法 (转)
我之前在 <前端搭环境之从入门到放弃>这篇文章中吐槽过,webpack中可以写commonjs格式的require同步语法,可以写AMD格式的require回调语法,还有一个require ...
- 前端笔记之Vue(五)TodoList实战&拆分store&跨域&练习代理跨域
一.TodoList 1.1安装依赖 安装相关依赖: npm install --save-dev webpack npm install --save-dev babel-loader babel- ...
- 翻译 | 关键CSS和Webpack: 减少阻塞渲染的CSS的自动化解决方案
原文地址: Critical CSS and Webpack: Automatically Minimize Render-Blocking CSS 原文作者: Anthony Gore 译者: 蜗牛 ...
- 【翻译】Webpack 4 从0配置到生产模式
查看原文 webpack 4 发布了! webpack 4 作为一个零配置的模块打包器 webpack 是强大的并且有许多独一无二的特点但是有一个痛点就是配置文件. 在中型到大型项目中为webpack ...
- 翻译 | 上手 Webpack ? 这篇就够了!
译者:小 boy (沪江前端开发工程师) 本文原创,转载请注明作者及出处. 原文地址:https://www.smashingmagazine.com/2017/02/a-detailed-intro ...
- webpack+react+redux+es6开发模式
一.预备知识 node, npm, react, redux, es6, webpack 二.学习资源 ECMAScript 6入门 React和Redux的连接react-redux Redux 入 ...
- vue+ vue-router + webpack 踩坑之旅
说是踩坑之旅 其实是最近在思考一些问题 然后想实现方案的时候,就慢慢的查到这些方案 老司机可以忽略下面的内容了 1)起因 考虑到数据分离的问题 因为server是express搭的 自然少 ...
随机推荐
- 2014年辛星PHP教程秋季版第一本即基础知识已经完工
因为本人还是蛮重视秋季版的,因此一開始就决定要把它做好,因此体系划分的比較具体,如今把它的第一本写作完成,在百度的下载点是:点我去百度 ,它的五十多个实例代码在百度的下载点是:点我下载源代码 ,当然, ...
- WebStorm中Node.js项目配置教程(1)——创建项目
Node.js绝对是一个web开发的热点话题,作为web神器的WebStorm也是开发Node.js的佼佼者. 接下来就Node.js项目在WebStorm的配置操作就行详细的讲解,首先是创建项目.两 ...
- leetcode第39题--Combination Sum II
题目: Given a collection of candidate numbers (C) and a target number (T), find all unique combination ...
- 单极型ADC如何测量负电压?
最常用的方法是使用一个运放做成加法器将负电压抬到0V以上,如果这样的输出超过了最大输出电压那么再使用比例衰减就可以办到了. 参考下面的讨论: http://www.amobbs.com/thread- ...
- js实现文字横向滚动
页面布局 <div id="scroll_div" class="fl"> <div id="scroll ...
- ASP.NET中Partial Class部分类
原文:ASP.NET中Partial Class部分类 如果您在开发项目的公用函数库,用于公用函数库的内容越丰富越好,但这不可能一下子就写好,需要一点一点的积累,这时就可以使用Partial Clas ...
- socket计划——一个简单的例子
从一个简单易用TCP样品开始socket计划,的基本过程例如下列: server client +++ ...
- 为ASP.NET MVC应用程序实现继承
为ASP.NET MVC应用程序实现继承 这是微软官方教程Getting Started with Entity Framework 6 Code First using MVC 5 系列的翻译,这里 ...
- Moq的使用心得
Moq的使用心得 1.Moq中Mock Repository时最好是Mock Repository的接口,这样会避免不知名的错误. var mockClubRepository = new Mock& ...
- -协同IResult
Caliburn.Micro学习笔记(五)----协同IResult 今天说一下协同IResult 看一下IResult接口 /// <summary> /// Allows cust ...