webpack-易混淆部分的解释
原文链接:
https://medium.com/@rajaraodv/webpack-the-confusing-parts-58712f8fcad9
webpack的核心哲学
1. 任何皆模块
正如js文件可以是"modules",任何其他的文件,比如css, images, html都可以被视为modules。也就是说,你可以通过require("myJSfile.js")来加载js文件,也可以通过require("mycssFile.css")加载css文件。这也就意味着我们可以将任何工作成果视为更小的可管理的构建,可用于重用。
2. 仅仅在你需要使用的时候,仅仅加载你需要的asset. 典型的,打包器接收所有的模块输入而最终生成以恶搞巨大的单个"bundle.js"文件.但是很多真实的应用,这个bundel.js文件可能会达到10MB-15MB的大小!因此,这种情况下会导致加载非常慢。webpack为了处理这种bundle过大的问题,webpack提供了几个好用的功能用于split你的代码,并且产生出多个"bundle" files,并且可以async异步地加载parts of the app,以便仅仅加载你当前需要的部分。
下面我们来一个个探讨容易搞不清楚的webpack topic
Development vs production
首先我们要铭记在心的是webpack有非常朵的好功能,而这些功能中很大一部分仅仅是为"development-only"的功能,而一部分是"production-only"的,而剩下的部分是既可用于开发环境,又可用于生产环境。
典型地,大多数项目通过使用两个大的webpack config file来分别处理dev和prod两种场景。
要创建bundle,你可能会在package.json中这样写:
"scripts":{
// npm run build to build production bundles
"build": "webpack --config webpack.config.prod.js",
// npm run dev to generate development bundles and run dev server
"dev": "webpack-dev-server"
}
webpack CLI vs webpack-dev-server
webpack,作为打包工具,提供以下两个接口,理解这一点非常重要:
1. webpack cli tool---这是默认的接口(随着webpack的安装而存在于.bin目录中)
2. webpack-dev-server tool ---一个node.js server(你需要单独安装它)
webpack CLI(非常适合做prodcution build)
这个命令行工具通过cli接收一些配置option,或者通过一个config file来接收这些option(默认为webpack.config.js配置文件),这些配置选项将用于webpack的打包过程。
虽然你可能是通过使用cli来开始学习webpack的,但是实际上命令行工具往往更多用于创建生产环境下使用的bundle.
用法:
OPTION :
//Install it globally
npm install webpack --g
//Use it at the terminal
$ webpack //<--Generates bundle using webpack.config.js OPTION :
//Install it locally & add it to package.json
npm install webpack --save
//Add it to package.json's script
“scripts”: {
“build”: “webpack --config webpack.config.prod.js -p”,
...
}
//Use it by running the following:
"npm run build"
webpack-dev-server(非常适合创建开发的build,并serve静态的assets)
webpack-dev-server是一个运行于8080端口的expresss nodejs server.这个server会自己调用webpack本身实现构建,并且server构建出来的bundle.这个server的好处是它可以提供比如"Live Reloading"或者"Hot Module Replacement(HMR)"的实用功能。
npm install webpack-dev-server --save
//Use it at the terminal
$ webpack-dev-server --inline --hot
OPTION :
// Add it to package.json's script “scripts”: {
“start”: “webpack-dev-server --inline --hot”,
...
}
// Use it by running
$ npm start
Open browser at:
http://localhost:8080
webpack vs webpack-dev-server options
需要说明的是,比如"inline"或者"hot"这些配置选项仅仅是对webpack-dev-server来适用的。而比如"hide-modules"仅仅针对webpack cli来说是适用的。
webpack-dev-server CLI options vs config options
另外需要说明的一点是:你可以通过以下两种方式来传入webpack-dev-server配置选项options:
1. 通过webpack.config.js的"devServer对象
2.通过webpack-dev-server的CLI options传入:
//Via CLI
webpack-dev-server --hot --inline
//Via webpack.config.js
devServer: {
inline: true,
hot:true
}
我在测试中发现,有时通过devServer配置选项传入参数(hot:true, inline:true)并不总是能够工作,所以,我更喜欢通过在package.json中的cli option来传入对应的参数:
//package.json
{
scripts:
{“start”: “webpack-dev-server --hot --inline”}
}
"hot" vs "inline" webpack-dev-server options:
"inline"选项使得针对整个页面实现"live reloading"成为可能。"hot"选项使能了"hot module reloading"功能,而这个功能可以仅仅reload那些被变更过的component(而不是整个页面重新加载).如果我们同时传入两个配置选项,那么当source变化时,webpack-dev-server将会首先试图做HRM,如果HMR不work,则会reload整个页面。
//When the source changes, all 3 options generates new bundle but, //1. doesn't reload the browser page
$ webpack-dev-server
//2. reloads the entire browser page
$ webpack-dev-server --inline
//3. reloads just the module(HMR), or the entire page if HMR fails
$ webpack-dev-server --inline --hot
"entry" --String Vs Array Vs Object
Entry这个配置项告诉webpack应用的root module或者starting point在哪里。这个配置项可以是string,可以是array,也可以是object.这个灵活性可能让我们搞得糊涂,但是这些不同类型的数据实际上是用于不同的目的的。
如果你有一个single starting point的话,那么string, array, object都是一样的结果。
entry-array
但是,如果你想追加多个互不依赖的文件,那么可以使用array格式
比如,你可能需要"googleAnalytics.js"到你的html中,那么你可以告诉webpack追加该analytics.js到bundle.js的后面:
entry-object
如果你有一个多页的web应用,有多个html文件(index.html, profile.html等),而不是一个SPA w/ multi-views,
那么你可以通过entry object告诉webpack需要一次性创建多个bundles。
下面的配置将产生两个js bundle文件:indexEntry.js和profileEntry.js分别应用于index.html和profile.html中
使用方法为:
//profile.html
<script src=”dist/profileEntry.js”></script>
//index.html
<script src=”dist/indexEntry.js”></script>
entry-combination
你也可以在object entry里面使用array entries。例如,下面的config将产生3个文件:vendor.js和index.js, profile.js:
output-"path" vs "publicPath"
output告诉webpack我们将最终的输出存放在哪里一级如何存放。这里两个参数:path和publicPath可能会产生歧义和误解。
"path"告诉webpack我们将最终的bundle存放在哪里。耳"publicPath"则被多个webpack plugin来使用用于当产生production build时更新在html,css文件中的url
例如,在你的css中,你可能有一个url从你的localhost来load './test.png‘。但是在生产环境下,test.png文件可能存在于CDN中。这意味着你可能需要手工的更新这些url以便在生产环境中可以指向到正确的url地址。
为了解决这个手工修改url的问题,你可以使用webpack的publicPath参数,而这个参数对几乎所有的plugin都是能够理解并使用这个publicPath参数的,并且自动在创建production build时更新这些url.
// Development: Both Server and the image are on localhost
.image {
background-image: url(‘./test.png’);
}
// Production: Server is on Heroku but the image is on a CDN
.image {
background-image: url(‘https://someCDN/test.png’);
}
loaders and chaning loaders
loaders是一些额外的node modules专门用于帮助'load'或者'import'各种类型的文件到浏览器可以认识的js, css文件格式。更进一步,loader也允许通过require或者import来import这些文件到js中。
例如:你可以使用bable-loader来转换es6写的js代码到浏览器可以认识的es5 javascript:
module: {
loaders: [{
test: /\.js$/, ←Test for ".js" file, if it passes, use the loader
exclude: /node_modules/, ←Exclude node_modules folder
loader: ‘babel’ ←use babel (short for ‘babel-loader’)
}]
chaining loaders(从右往左)
多个loaders可以级联起来,针对同一个文件做不同的转换。级联是从右往左工作的,同时使用" ! "来隔离
例如,我们如果有一个"mycssfile.css"文件,我们需要将它的内容dump到html的<style>css content</style>中。我们可以通过以下两个loaders来实现这个功能:css-loader和style-loader
module: {
loaders: [{
test: /\.css$/,
loader: ‘style!css’ <--(short for style-loader!css-loader)
}]
下面这张图可以解释这个过程是如何工作的:
1. 首先webpack在module中检索相关依赖,webpack看到mycssfile.css通过require来做import,因此mycssfile.css将作为dependency来处理,webpack首先将该css文件给到'css-loader'来做处理
2. css-loader加载所有的css内容以及该css内容中自己的depency(比如@import othercss),并保存为json. webpack然后将这个结果传给style-loader继续处理。
3. style-loader则接收这个json,并且增加<style>css contents</style>并将这个字符串插入到index.html文件中
loaders Themselves can be configured
loaders可以通过传入不同的parameters以不同的方式来工作。
在下面的例子中,我们配置url-loader当image小于1024字节的话直接使用DataURLs。我们可以传入limit参数来指定这个大小。
.babelrc文件
babel-laoder使用"presets"配置选项使能如何转换es6为es5的过程,一级如何解析react’s jsx 到js文件。我们可以通过query参数传入配置:
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /(node_modules|bower_components)/,
loader: 'babel',
query: {
presets: ['react', 'es2015']
}
}
]
}
然而,很多项目中babel的配置项目可能很多,这种情况下,你就可以把balble的这些配置项目放到.babelrc文件中去。babel-loader将自动加载这个.babelrc文件如果它存在的话。
所以在很多例子中,你可能会看到:
//webpack.config.js
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /(node_modules|bower_components)/,
loader: 'babel'
}
]
} //.bablerc
{
“presets”: [“react”, “es2015”]
}
Plugins
plugins是一些针对输出的bundle执行特别的工作的node modules.
例如,uglifyJSPlugin的作用是接收bundle.js作为输入并且混淆最小化该文件以减少文件的体积。
类似地,extract-text-webpack-plugin这个plugin则内部通过使用css-loader,style-loader来收集所有css内容并整合到一处并最终抽出这些css内容到一个单一的style.css文件中,并且在index.html中产生一个指向该style.css的link。
//webpack.config.js
//Take all the .css files, combine their contents and it extract them to a single "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
]
}
需要说明的是,如果你想在html中inline使用这些css样式,你可以不使用该plugin,而仅仅通过使用css, style loaders达到目的:
module: {
loaders: [{
test: /\.css$/,
loader: ‘style!css’ <--(short for style-loader!css-loader)
}]
loaders vs plugins
loaders仅在bundle生成过程中或者生成之前针对单个的文件做转换。
而plugin则在bundle创建的结束之后针对整个bundle或者chunk level执行操作。一些像commonsChunksPlugin的插件则更进一步会修正bundles本身是如何创建的过程。
resolving file extensions
很多webpack config文件有一个resolve extensions属性,并有一个空字符串作为值。
这个空字符串用于帮助resolve imports without extensions,比如require("./myJSFile")或者import myJSFile从"./myJSFile”而不用加上文件的扩展名.
{
resolve: {
extensions: [‘’, ‘.js’, ‘.jsx’]
}
}
webpack-易混淆部分的解释的更多相关文章
- C#中一些易混淆概念总结
C#中一些易混淆概念 这几天一直在复习C#基础知识,过程中也发现了自己以前理解不清楚和混淆的概念.现在给大家分享出来我的笔记: 一,.NET平台的重要组成部分都是有哪些 1)FCL (所谓的.NET框 ...
- [Swift-2019力扣杯春季初赛]1. 易混淆数
给定一个数字 N,当它满足以下条件的时候返回 true: 把原数字旋转180°以后得到新的数字. 如 0, 1, 6, 8, 9 旋转 180° 以后,得到了新的数字 0, 1, 9, 8, 6 . ...
- 【C#小知识】C#中一些易混淆概念总结(六)---------解析里氏替换原则,虚方法 分类: C# 2014-02-08 01:53 1826人阅读 评论(0) 收藏
目录: [C#小知识]C#中一些易混淆概念总结--------数据类型存储位置,方法调用,out和ref参数的使用 [C#小知识]C#中一些易混淆概念总结(二)--------构造函数,this关键字 ...
- 【C#小知识】C#中一些易混淆概念总结(五)---------继承 分类: C# 2014-02-06 22:05 1106人阅读 评论(0) 收藏
目录: [C#小知识]C#中一些易混淆概念总结--------数据类型存储位置,方法调用,out和ref参数的使用 [C#小知识]C#中一些易混淆概念总结(二)--------构造函数,this关键字 ...
- 【C#小知识】C#中一些易混淆概念总结(五)---------深入解析C#继承
目录: [C#小知识]C#中一些易混淆概念总结--------数据类型存储位置,方法调用,out和ref参数的使用 [C#小知识]C#中一些易混淆概念总结(二)--------构造函数,this关键字 ...
- 【C#小知识】C#中一些易混淆概念总结(四)---------解析Console.WriteLine() 分类: C# 2014-02-05 17:18 1060人阅读 评论(0) 收藏
目录: [C#小知识]C#中一些易混淆概念总结 [C#小知识]C#中一些易混淆概念总结(二) [C#小知识]C#中一些易混淆概念总结(三) ------------------------------ ...
- 【C#小知识】C#中一些易混淆概念总结---------数据类型存储,方法调用,out和ref参数的使用
这几天一直在复习C#基础知识,过程中也发现了自己以前理解不清楚和混淆的概念.现在给大家分享出来我的笔记: 一,.NET平台的重要组成部分都是有哪些 1)FCL (所谓的.NET框架类库) 这些类是微软 ...
- css常见的易混淆属性和值的区别(一)
css的属性很多,每一个属性的值也很多,组合起来便有成千上万种.不同属性之间的相互组合也可以产生不同的样式,css真是一种优美的样式设计语言.下面对工作中常见的易混淆的属性和值进行总结: 1. lin ...
- C#中易混淆的知识点
C#中易混淆的知识点 一.引言 今天在论坛中看到一位朋友提出这样的一个问题,问题大致(问题的链接为:http://social.msdn.microsoft.com/Forums/zh-CN/52e6 ...
- a链接易混淆与form表单简易验证用法详解
链接可以说遍布互联网,比如你想提供一个可以跳转到百度首页的链接给网友,那么代码如下: <a href="http://www.baidu.com">百度一下,你就知道& ...
随机推荐
- ERROR:org.apache.hadoop.hbase.PleaseHoldException: Master is initializing 解决方案
我尝试的过程如下 1. 时间没有同步 用date命令看一下每个机器 如果时间差距大 说明确实有问题 ** 配置时间服务器 ** 检查时区 $ d ...
- EditText格式化11位手机号输入xxx xxxx xxxx
EditText格式化11位手机号输入xxx xxxx xxxx /** * 格式化11位手机号码输入 xxx xxxx xxxx格式 * 如果一直是添加:输入到第三个或第8个数字时 ...
- ES6-Array
/* * 数组解构赋值: * ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这种被称为解构. * 示例如下: */ var [a,b,c] = [1,2,3]; console.log ...
- Linux用户权限规范 /etc/sudoers文件解释
# User privilege specification root ALL=(ALL) ALL # Members of the admin group may gain root privile ...
- WPF中触发器(Trigger、DataTrigger)使用动画最简单的方式EnterActions和ExitsActions
1.当鼠标移入后执行某个动画: <Style TargetType="{x:Type StackPanel}"> <Setter Property="R ...
- HwUI下载地址
下载地址:HwUI.0.0.1.zip
- python学习之老男孩python全栈第九期_day029知识点总结——configparser模快、logging模块
一. configparser模块 生成文档 import configparser config = configparser.ConfigParser() config[', 'Compressi ...
- nodejs中创建web服务,监听本地IP
nodejs官网例子 var http = require('http'); http.createServer(function (req, res) { res.writeHead(200, {' ...
- R包下载的一些小问题
install.packages(c("matrixStats", "Hmisc", "splines", "foreach&qu ...
- 详解php常量const与define的区别和实例
所谓常量是一个简单的标识符.在脚本执行期间该值不能改变.常量默认大小写敏感.通常常量标识符总是大写的.常量只能包含标量数据(boolean.integer.float和string).可以定义reso ...