React系列文章:Webpack模块组织关系
现代前端开发离不开打包工具,以Webpack为代表的打包工具已经成为日常开发必备之利器,拿React技术栈为例,我们ES6形式的源代码,需要经过Webpack和Babel处理,才能生成发布版文件,在浏览器中运行。今天就结合React来梳理一下Webpack打包时模块的组织结构,先给定下面一个简单的应用示例:
import React from 'react';
import ReactDOM from 'react-dom';
import {greet} from './utils';
const App = <h1>{greet('scott')}</h1>;
ReactDOM.render(App, document.getElementById('root'));
代码中的utils模块如下:
export function greet(name) {
return `hello ${name}`;
}
如果编译该示例代码,由于要将第三方库一起打包,最终生成的目标代码会比较多,所以我们先在webpack.config.prod.js中将React和ReactDOM配置为externals,不将它们编译到目标代码中,而是在运行时直接从外部取值。配置如下:
let appConfig = {
entry: './src/index.js',
externals: {
'react': 'React',
'react-dom': 'ReactDOM',
},
output: {
path: './dist',
filename: 'index.js'
},
module: {
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
}
]
},
};
运行webpack,生成的目标代码如下:
(function (modules) {
// 存放已加载的模块
var installedModules = {};
// 加载函数
function __webpack_require__(moduleId) {
// 如果该模块已被加载 直接返回module.exports
if (installedModules[moduleId]) {
return installedModules[moduleId].exports;
}
var module = installedModules[moduleId] = {
exports: {},
id: moduleId,
loaded: false
};
// 调用模块函数 加载相应的模块
// 参数是(module, exports[, __webpack_require__])
modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
// 标记该模块已被加载
module.loaded = true;
// 最后也返回exports
return module.exports;
}
// 暴露modules和installedModules对象
__webpack_require__.m = modules;
__webpack_require__.c = installedModules;
// __webpack_public_path__
__webpack_require__.p = "";
// 加载主模块
return __webpack_require__(0);
})
/* 以下是模块列表 作为参数被加载 */
([
/* 0 主模块 */
(function (module, exports, __webpack_require__) {
'use strict';
// 取索引为1的React模块
var _react = __webpack_require__(1);
var _react2 = _interopRequireDefault(_react);
// 取索引为2的ReactDOM模块
var _reactDom = __webpack_require__(2);
var _reactDom2 = _interopRequireDefault(_reactDom);
// 取索引为3的utils模块
var _utils = __webpack_require__(3);
// 模块取值 不包含__esModule:true的是默认导出
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : { default: obj };
}
// 开始渲染视图
var App = _react2.default.createElement(
'h1',
null,
(0, _utils.greet)('scott')
);
_reactDom2.default.render(App, document.getElementById('root'));
}),
/* 1 React模块 */
(function (module, exports) {
module.exports = React;
}),
/* 2 ReactDOM模块 */
(function (module, exports) {
module.exports = ReactDOM;
}),
/* 3 utils模块 */
(function (module, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.greet = greet;
function greet(name) {
return "hello " + name;
}
})
]);
上面就是基本的模块加载机制。其实,有了externals配置,我们也可以不在代码中引入React和React-DOM,下面稍微修改一下代码:
import {greet} from './utils';
const App = <h1>{greet('scott')}</h1>;
ReactDOM.render(App, document.getElementById('root'));
转译后的代码如下:
(function (modules) {
// ...
})
/* 以下是模块列表 作为参数被加载 */
([
/* 0 主模块 */
(function (module, exports, __webpack_require__) {
'use strict';
// 取索引为1的utils模块
var _utils = __webpack_require__(1);
// 开始渲染视图
var App = React.createElement(
'h1',
null,
(0, _utils.greet)('scott')
);
ReactDOM.render(App, document.getElementById('root'));
}),
/* 1 utils模块 */
(function (module, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.greet = greet;
function greet(name) {
return "hello " + name;
}
})
]);
可以看到,代码清晰了不少,主模块中直接调用React.createElement()来创建虚拟DOM对象,最后调用ReactDOM.render()方法来渲染真实的DOM结点。访问下面的入口文件,我们就可以看到程序运行的结果:
<!DOCTYPE html>
<html>
<body>
<div id="root"></div>
<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
<script src="index.js"></script>
</body>
</html>
React系列文章:Webpack模块组织关系的更多相关文章
- React系列文章:Babel编译JSX生成代码
上次我们总结了React代码构建后的Webpack模块组织关系,今天来介绍一下Babel编译JSX生成目标代码的一些规则,并且模拟整个生成的过程. 我们还是拿最简单的代码举例: import {gre ...
- React: webpack模块组织关系
现代前端开发离不开打包工具,以 webpack 为代表的打包工具已经成为日常开发必备之利器,拿 React 技术栈为例,我们 ES6 形式的源代码,需要经过 webpack 和 Babel 处理,才能 ...
- React 系列文章(1): npm 手动搭建React 运行实例 (新手必看)
摘 要 刚接触React 开发, 在摸索中构建react 运行环境,总会遇到各种坑:本文,将用最短时间解决webpack+react 环境搭建问题. 1.如果你还没有React基础 看这里. 2.如果 ...
- React系列文章:无状态组件生成真实DOM结点
在上一篇文章中,我们总结并模拟了JSX生成真实DOM结点的过程,今天接着来介绍一下无状态组件的生成过程. 先以下面一段简单的代码举例: const Greeting = function ({name ...
- React系列文章:JSX生成真实DOM结点
在上一篇文章中,我们介绍了Babel是如何将JSX代码编译成可执行代码的,随后也实现了一个自己的解析器,模拟了Babel编译的过程. 现在我们再来回顾一下,假定有如下业务代码: const style ...
- 关于Webpack详述系列文章 (第二篇)
1.缩小文件搜索范围 1.1.1 include & exclude module:{ rules:[ { test:/\.js$/, use:['babel-loader?cacheDire ...
- 关于Webpack详述系列文章 (第三篇)
1. 类图 1. 模块 Module是webpack中最核心的类,要加载定的一切和依赖都是Module. 它有很多子类 RawModule NormalModule MultiModule Conte ...
- [React] react+redux+router+webpack+antd环境搭建一版
好久之前搭建的一个react执行环境,受历史影响是webpack3.10.0和webpack-dev-server2.7.1的环境,新项目准备用webpack4重新弄弄了,旧的记录就合并发布了(在没有 ...
- React系列之--props属性
版权声明:本文为博主原创文章,未经博主允许不得转载. PS:转载请注明出处作者:TigerChain地址:http://www.jianshu.com/p/fa81cebac3ef本文出自TigerC ...
随机推荐
- ASP.NET Core Identity 实战(3)认证过程
如果你没接触过旧版Asp.Net Mvc中的 Authorize 或者 Cookie登陆,那么你一定会疑惑 认证这个名词,这太正式了,这到底代表这什么? 获取资源之前得先过两道关卡Authentica ...
- @RequestBody,@ResponseBody
@RequestBody 作用: i) 该注解用于读取Request请求的body部分数据,使用系统默认配置的HttpMessageConverter进行解析,然后把相应的数据绑定到要返回的对象上: ...
- saltstack中如何实现多个master来管理minion
背景: 公司有多个部门,有一些机器有本部门的业务,这些机器也有其他部门的业务,所以本部门需要一个master服务器来管理这批机器,其他部门也需要一个master服务器来管理这个机器,所以就需要多个ma ...
- centos6.5下编译安装mariadb-10.0.20
源码编译安装mariadb-10.0.20.tar.gz 一.安装cmake编译工具 跨平台编译器 # yum install -y gcc* # yum install -y cmake 解决依赖关 ...
- jmeter之使用代理录制脚本
从loadrunner到jmeter,录制压力测试脚本好像都只支持IE,近来才知道jmeter还有自带的录制脚本元件, 且支持IE.Chrome及Firefox等多种浏览器.这里就记录一下通过jmet ...
- .net下web页生产一维条形码
code-39 前台 aspx <asp:Image ID="imgBandCode" runat="server" ImageUrl="~/W ...
- 《java程序设计》结对编程-四则运算(第一周-阶段总结)
一.需求分析(描述自己对需求的理解,以及后续扩展的可能性) 实现一个命令行程序,要求: - 自动生成小学四则运算题目(加,减,乘,除) - 支持整数 - 支持多运算符(比如生成包含100个运算符的题目 ...
- OCM_第五天课程:Section2 —》AGENT 的安装 、GC 的使用
注:本文为原著(其内容来自 腾科教育培训课堂).阅读本文注意事项如下: 1:所有文章的转载请标注本文出处. 2:本文非本人不得用于商业用途.违者将承当相应法律责任. 3:该系列文章目录列表: 一:&l ...
- bzoj3224 splay板子
开始学习新知识:splay——tree 是个板子题,学习splay可以看博客 https://blog.csdn.net/Clove_unique/article/details/50630280 # ...
- 设计模式【转自JackFrost的博客】
首先,感谢作者对知识的分享 使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性.设计模式使代码编制真正工程化,是软件工程的基石脉络,如同大厦的结构一样. 文章结构:1.单一职责原则( ...