concepts
webpack是JS应用程序的静态模块打包工具。webpack在处理你的应用时,会递归的构建依赖项,这些依赖项包括你的应用程序所需要的所有模块,然后把这些模块打包到一个或多个bundles中。
一、Entry
entry point是项目的入口文件,告诉webpack从哪个模块开始构建内部依赖。进入入口文件后,webpack会直接或间接的找到其依赖的模块和库。
1、定义入口的方式有多种:
1)简写形式(string | array<string>)
module.exports = {
entry: './path/to/my/entry/file.js'
}
module.exports = {
entry: {
main: './path/to/my/entry/file.js'
}
}
上面的写法实际上是下面写法的简写形式
multi-main entry: entry是一个存放文件路径的数组,当你需要将多个依赖文件一起注入并将它们的依赖关系打包成一个chunk时,可以使用这种方式。
2)对象形式({ [entryChunkName]: string|array<string> })
const config = {
entry: {
app: './src/app.js',
vendors: './src/vendors.js'
}
}
2、应用场景
1)分离app和vendor入口
const config = {
entry: {
app: './src/app.js',
vendors: './src/vendors.js'
}
}
这种形式告诉webpack从app.js和vendors.js开始创建分离的相互独立的依赖。这在单页面应用中很常用。这种设置允许你利用CommonsChunkPlugin将应用中任何vendor的引用抽离到vendor bundle. 这样在你的应用程序bundle中就没有vendor代码。
2)多页面应用
const config = {
entry: {
pageOne: './src/pageOne/index.js',
pageTwo: './src/pageTwo/index.js',
pageThree: './src/pageThree/index.js'
}
};
这种设置方式告诉webpack我们有3个分离的依赖项。在多页面应用中,服务器需要获取新的HTML文档,页面重新加载新的文档和文件需要重新下载,这样我们就可以使用CommonsChunkPlugin将页面间共享的代码提取打包。
黄金条例:每个HTML文档使用一个入口。
二、Output
output属性告诉webpack打包文件的输出位置和名字。 output是一个对象,一般需要文件名(filename)和输出路径(path);
const path = require('path');
module.exports = {
entry: './path/to/my/entry/file.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'my-first-webpack.bundle.js'
}
};
1、多入口文件
当你的设置会有多个chunk(比如多个入口文件或者使用类似CommonsChunkPlugin)时使用,但你需要保证每个文件都有唯一的名字。
{
entry: {
app: './src/app.js',
search: './src/search.js'
},
output: {
filename: '[name].js',
path: __dirname + '/dist'
}
}
2、publicPath
当你将应用所需文件存放在CDN或者hash时
output: {
path: "/home/proj/cdn/assets/[hash]",
publicPath: "http://cdn.example.com/assets/[hash]/"
}
如果编译时不确定最终的publicPath,这个值可以设为空白或者不设置,然后在入口文件中使用__webpack_public_path__动态设置。
__webpack_public_path__ = myRuntimePublicPath // rest of your application entry
三、Loaders
loaders可以帮助webpack处理更多类型的文件,不仅限于javascript(webpack自身只能处理JS)。loaders会将各种类型的文件转化为webpack能处理的合法模块。
1、使用方式
1) 配置文件
const path = require('path');
module.exports = {
entry: './path/file.js',
output:{
path: path.resolve(__dirname,'dist'),
filename:'bundle.js',
},
modules:{
rules: [
{test: /\.txt$/, use: 'raw-loader'},
{
test: /\.css$/,
use: [
{ loader: 'style-loader' },
{
loader: 'css-loader',
options: {
modules: true
}
}
]
}
]
}
}
2)inline
import Styles from 'style-loader!css-loader?modules!./styles.css';
options可以通过query参数形式传递,比如?key=value&foo=bar,或者JSON对象形式,比如?{"key":"value","foo":"bar"}
3) CLI
webpack --module-bind jade-loader --module-bind 'css=style-loader!css-loader'
四、Plugins
plugins可以做更多的事情,可以优化和更小化打包文件,或者定义环境变量。
plugin是一个JS对象,有apply属性。apply属性会被webpack的编译器调用,允许进入整个编译周期。
function ConsoleLogOnBuildWebpackPlugin() {
};
ConsoleLogOnBuildWebpackPlugin.prototype.apply = function(compiler) {
compiler.plugin('run', function(compiler, callback) {
console.log("The webpack build process is starting!!!");
callback();
});
};
plugins: [
new webpack.optimize.UglifyJsPlugin(),
new HtmlWebpackPlugin({template: './src/index.html'})
]
五、Module Resolution
resolver帮助webpack定位模块位置。依赖模块可能来自应用程序中的代码或者第三方库,resolver可以帮助webpack找到模块代码,这些模块代码通过require/import引入,并被打包到bundle中。
1、resolving rules
1)绝对路径
import "/home/me/file"; import "C:\\Users\\me\\file";
因为已经包含了文件绝对路径,所以不需要其他的resolution。
2)相对路径
import "../src/file1";
import "./file2";
在这种情况下,源文件所在文件夹将作为context directory,然后将这些相对路径加入到context路径中生成模块的绝对路径。
3)Module path
import "module";
import "module/lib/file";
resolve.modules下的所有文件夹都会被搜索。你可以使用resolve.alias创建原始Module 路径的别名。
一旦通过上面的规则解析出了路径,resolve会检查该路径指向的是一个文件还是一个文件夹。
如果是文件:
该路径带有文件扩展名,那么文件直接被打包;否则,使用resolve.extensions解析出文件扩展名。
如果指向的是文件夹:
文件夹包含package.json文件,package.json中出现的第一项resolve.mainFields配置项中的文件决定最终的文件路径。如果文件夹中没有package.json文件,或者main fields中没有返回一个合法的路径,依次匹配resolve.mainFields配置项中指定的文件名,看是否找到匹配的文件路径。至于文件扩展名,仍然使用resolve.extensions来解析。
2、resolving loaders
3、caching
每个文件系统都是被缓存的,因此对一个文件的多个平行或者一系列请求会很快。在watch mode,只有修改过的文件会从缓存中删去。如果watch mode被关闭,那么缓存会在每次编译前清除。
六、Targets
因为JS可以用在服务端和浏览器端,你可以在webpack配置文件中配置部署目标。
1、使用
module.exports = {
target: 'node'
};
在上面的例子中,使用node,webpack会编译一个类似nodejs的环境。target默认设置为web
2、multiple target
虽然webpack不支持给target传多个字符串,但是可以构建两个独立的配置来创建同构的库
var path = require('path');
var serverConfig = {
target: 'node',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'lib.node.js'
}
//…
};
var clientConfig = {
target: 'web', // <=== can be omitted as default is 'web'
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'lib.js'
}
//…
};
module.exports = [ serverConfig, clientConfig ];
这样会在你的dist文件夹下生成lib.js和lib.node.js两个文件。
https://github.com/TheLarkInn/compare-webpack-target-bundles
七、manifest
基本上在一个基于webpack的应用中,会出现三种类型的code:
- 应用源代码
- 第三方库或者源代码依赖的vendor code
- 联系各个模块的runtime 和 manifest
1、 Runtime
当你的应用在浏览器中运行时,runtime和manifest数据基本上是webpack联系你的模块化应用所需的所有code。它包含你的模块之间交互时,链接各个模块所需要的加载和解析逻辑。这包括了连接已经加载到浏览器中的模块,以及延迟加载的模块。
2、manifest
那么当你的应用以index.html文件在浏览器中运行时,那些bundles和其他的文件是什么样的呢?src目录下你写的代码都没有了,那么webpack是怎么处理modules之间的交互的呢?这就是manifest data用到的地方。。。
当编译器进入,解析并映射你的应用时,会一直关注你的modules。这些数据集合就是manifest,当这些modules bundled并且加载进浏览器时,runtime就会利用manifest来解析和加载modules。不管你用的是什么模块语言,import和require都会变为指向module identifiers的__webpack_require__方法。使用manifest中的数据,runtime可以找到这些identifiers后的module位置。
3、problem
这些内容平时一般都用不到,但是如果你想要使用浏览器缓存优化你的应用性能,就需要知道上面这些概念了。
将bundle文件名哈希表示,你可以告诉浏览器文件内容改变了,缓存已经没用了。但如果你这样做,你会发现,有时候文件内容没变,文件名的哈希表示也会变化。这就是因为runtime和manifest在每次构建时都会改变。
八、Hot Module Replacement
应用程序在运行时不需要重新加载页面,HMR就可以修改,添加和删除modules。这在几个方面加速开发过程:
- 保存应用在重新加载时会丢失的状态;
- 只更新改变的内容,节约宝贵的开发时间
- 更快的调整样式,几乎可以和浏览器开发者模式中调整样式一样快速生效
How it works
1、in the application
1)应用程序要求HMR runtime检查更新
2)runtime异步下载更新并通知应用程序
3)应用程序要求runtime应用更新
4)runtime同步应用更新
设置HMR,上面的步骤就会自动发生处理,或者也可以通过用户的交互来更新
2、in the compiler
除了更新普通的文件,编译器还需要发出更新信号,来允许从旧的版本更新到新的版本。这个更新包括两个部分:
- 更新后的manifest(JSON)
- 一个或多个更新后的chunks(JS)
manifest包含新的编译hash和所有更新后的chunks清单。每一个这种chunks包含所有更新过的modules 的新code(或者是一个flag表示module被删除)。
编译器会确保在这些构建中module id和chunk id一致,并将这些ID保存在内存中或者JSON文件中。
3、in a module
HMR只会影响包含HMR code的modules。比如style-loader,它实现了HMR接口,当从HMR接收到更新,会用新的样式替换旧的样式。
同样的,当在一个module实现HMR接口时,你可以根据module是否更新来决定接下来应该做什么。但是,在大多数情况下,不需要强制在每个module中写HMR code。如果一个module没有HMR处理机制,更新会冒泡。这意味着,一个单独的处理器可以更新整个module tree。如果一个单独的module被更新了,那么所有依赖项都会重新加载。
4、in the runtime
对于module system runtime,会有额外的代码来追踪module的parents和children。在管理方面,runtime支持两个方法:check和apply。
check向更新的manifest发送HTTP请求。如果请求失败,表示没有可用更新。如果成功,会对比更新后的chunks清单和当前已加载chunks清单。对于每个已加载chunk,相应的更新chunk会被下载。所有module更新都保存在runtime。当所有更新的chunks被下载下来,并且已经准备应用更新,runtime会把状态调整为ready状态。
apply方法将所有更新modules标志为无效。对于每一个无效module,在module或者他的parents处需要有一个更新处理程序。否则,无效标志会向上冒泡,将Parents也标志为无效。冒泡会持续冒到应用程序的入口或者到达一个有更新处理程序的module。如果从entry point开始冒泡,那么进程失败。
然后所有无效modules通过卸载程序被卸载。当前hash被更新,所有accept handlers被调用。runtime切换回idle状态,一切回归正常。
concepts的更多相关文章
- 新书到手 TRANSACTION PROCESSING:CONCEPTS AND TECHNIQUES
新书到手 TRANSACTION PROCESSING:CONCEPTS AND TECHNIQUES Jim Gray大神的著作 本文版权归作者所有,未经作者同意不得转载.
- RS-232, RS-422, RS-485 Serial Communication General Concepts(转载)
前面转载的几篇文章重点介绍了UART及RS-232.在工控领域除了RS-232以外,常用的串行通信还有RS-485.本文转载的文章重点介绍了RS-232.RS-422和RS-485. Overview ...
- Deep Learning in a Nutshell: Core Concepts
Deep Learning in a Nutshell: Core Concepts This post is the first in a series I’ll be writing for Pa ...
- (转) Deep Learning in a Nutshell: Core Concepts
Deep Learning in a Nutshell: Core Concepts Share: Posted on November 3, 2015by Tim Dettmers 7 Comm ...
- AngularJs学习笔记--concepts(概念)
原版地址:http://code.angularjs.org/1.0.2/docs/guide/concepts 继续.. 一.总括 本文主要是angular组件(components)的概览,并说明 ...
- Part 16 Important concepts related to functions in sql server
Important concepts related to functions in sql server
- Basic Vlan Concepts
1. Vlan Benefit ·To reduce CPU overhead on each device by reducing the number of devices that recei ...
- Spring Batch Concepts Chapter
Spring Batch Concepts Chapter The below figure shows two kinds of Spring Batch components:infrastruc ...
- Six important .NET concepts 【Turn】
Introduction This article will explain six important concepts: stack, heap, value types, reference t ...
- Learing WCF Chapter1 Fundamental WCF Concepts
At its core,WCF is a development platform for service-oriented applications. As I mentioned earlier, ...
随机推荐
- Redis → Windows下搭建redis集群
一,redis集群介绍 Redis cluster(redis集群)是在版本3.0后才支持的架构,和其他集群一样,都是为了解决单台服务器不够用的情况,也防止了主服务器宕机无备用服务器,多个节点网络互联 ...
- 2019.9.17 csp-s模拟测试45 反思总结
来了来了,垃圾二连.[指两次发博客] 看了一下题就匆匆回去上课,在课上一边听课一边水oi,大概用1h40min的时间想完三道题.最后回到机房只剩下40min的时间敲代码,于是T1骗了70分就走了… 这 ...
- PHPStrom直接在编辑器打开php文件
以下是自己配置PHP+Apache的开发环境,集成环境的话要换第二种方法(看个人配置):PHPStrom 如果希望直接在编辑器打开php文件,要做以下这几步配置. 第一种:非集成环境 1 2 3 第二 ...
- Android消息机制使用注意事项,防止泄漏
在Android的线程通信当中,使用频率最多的就是Android的消息处理机制(Handler.send().View.post().Asynctask.excute()等等都使用到了消息处理机制). ...
- Django 自定义auth_user
1 导入AbstractUser from django.contrib.auth.models import AbstractUser 1 2 创建类UserProfile并继承AbstractUs ...
- 订阅 如何在IntelliJ IDEA中使用.ignore插件忽略不必要提交的文件
如何在IntelliJ IDEA中使用.ignore插件忽略不必要提交的文件 标签: idea git 插件 分类: Git 最近初学Git,而且在使用的IDE是IntelliJ IDEA,发现IDE ...
- oracle包头包体
补充说明:包头和包体可以以java的接口来理解,包头像java的接口,包体像java接口的实现类. 一 包的组成 包头(package):包头部分申明包内数据类型,常量,变量,游标,子程序和异常错误处 ...
- 配置了两天python【python可以的】
首先是看cs231n 发现代码的版本是py2 而我只装了 py3(anaconda3) 怎么办呢 于是想办法装了 anaconda2 并与之共存 ,调用的时候用 activate py2调用 http ...
- web服务器与tomcat
web服务器与tomcat 服务器分类: 硬件服务器和软件服务器 web服务器: 提供资源供别人访问 web: 网页的意思,资源. web资源分类: 动态的web资源:内容有可能发生改变的 静态的we ...
- tablespaces
select * from user_tablespaces; select username,default_tablespace from user_users;