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系列文章:Webpack模块组织关系
现代前端开发离不开打包工具,以Webpack为代表的打包工具已经成为日常开发必备之利器,拿React技术栈为例,我们ES6形式的源代码,需要经过Webpack和Babel处理,才能生成发布版文件,在浏 ...
- 部署React+webpack工程的步骤
# 部署React+webpack工程的步骤ps:以Mac os系统做开发环境.因为npm现在使用灰常的慢,所以我使用淘宝境像cnpm. 1,准备工作: 先确保存已经安装了node.js: 2,文件部 ...
- react webpack.config.js 入门学习
在学习react 的时候必然会用到webpack打包工具,webpack的快速入门另外一篇文章中有记录,这里只记录webpack.config.js文件,因为每个项目下都必须配置,通俗的讲,它的作用就 ...
- 真刀实战地搭建React+Webpack+Express搭建一个简易聊天室
一.前面bb两句 因为自惭(自残)webpack配置还不够熟悉,想折腾着做一个小实例熟悉.想着七夕快到了,做一个聊天室自己和自己聊天吧哈哈.好了,可以停止bb了,说一下干货. 二. 这个项目能学到啥? ...
- react常用模块介绍
react各个模块: 1.node.js自带的模块(原生模块):https://www.jianshu.com/p/abc72267abfc原生模块的api文档地址:http://nodejs.cn/ ...
- React + webpack 环境配置
安装配置Babel babel-preset-es2015 ES6语法包,使代码可以随意地使用ES6的新特性. babel-preset-react React语法包,专门用于React的优化,在代码 ...
- 每天记录一点:NetCore获得配置文件 appsettings.json vue-router页面传值及接收值 详解webpack + vue + node 打造单页面(入门篇) 30分钟手把手教你学webpack实战 vue.js+webpack模块管理及组件开发
每天记录一点:NetCore获得配置文件 appsettings.json 用NetCore做项目如果用EF ORM在网上有很多的配置连接字符串,读取以及使用方法 由于很多朋友用的其他ORM如S ...
- 用React & Webpack构建前端新闻网页
这是一篇给初学者的教程, 在这篇教程中我们将通过构建一个 Hacker News 的前端页面来学习 React 与 Webpack. 它不会覆盖所有的技术细节, 因此它不会使一个初学者变成大师, 但希 ...
- scss + react + webpack + es6
scss + react + webpack + es6 写在前面: 刚学习完慕课网里的一个幻灯片案例,自己加了刚学的react,两者结合.首先让大家看看效果 点击此处 你可以先用纯js实现上面的效果 ...
随机推荐
- xpath和contains模糊匹配
xpath可以以标签定位,也可以@任意属性: 如:以input标签定位:driver.find_element_by_xpath("//input[@id='kw']") 如:@t ...
- (原)理解码率控制模式(x264,x265,vpx)
理解码率控制模式(x264,x265,vpx) 原文链接:https://slhck.info/video/2017/03/01/rate-control.html 翻译:lihaiping1603@ ...
- 拼接Sql语句小心得
在往数据库插入数据时,需要根据数据和数据库中的列信息进行拼接,在本篇文章中,输出小心得.使用语言为 python. 拼接原始列信息 比如待插入数据库列信息为 deptNo,dName, Locate, ...
- ThinkPHP5远程代码执行高危漏洞(附:升级修复解决方法)
漏洞描述 由于ThinkPHP5框架对控制器名没有进行足够的安全检测,导致在没有开启强制路由的情况下,黑客构造特定的请求,可直接GetWebShell. 漏洞评级 严重 影响版本 ThinkPHP 5 ...
- myeclipse An internal error occurred during: "Initialize metrics".
重新安装的myeclipse,在打开的时候弹出: An internal error occurred during: "Initialize metrics". com/g ...
- 【ARM-Linux开发】OpenACC并行编程实战笔记
今年运气比较好,学了cuda之后,了解到了gpu的另两种使用语言opencl和openacc, opencl(Open Computing Language ,开放计算语言)是面向异构系统的并行编程 ...
- 解决angular+element原有组件样式不能覆盖element自带样式问题
在对应的组件中写入 ::ng-deep + 想要改变的element组件样式名即可
- 在ensp上配置RIPv2的认证
原理 实验模拟 实验拓扑 测试连通性 搭建rip网络 查看路由表 R3模拟攻击首先把在自己的的ip通告网段 配置完成后查看一下路由表 可以看到已经非法获取R1R2的网段信息,那么现在我们R3可以向两个 ...
- aspnetcore identity result.Succeeded SignInManager.IsSignedIn(User) false?
登陆返回的是 result.Succeeded 为什么跳转到其他页面SignInManager.IsSignedIn(User)为false呢? result.Succeeded _signInMan ...
- pyhthon Opencv截取视频中的图片
import os import cv2 ##加载OpenCV模块 def video2frames(pathIn='', pathOut='', imgname='', only_output_vi ...