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实现上面的效果 ...
随机推荐
- 码云push时提示 DeployKey does not support push code fatal: Could not read from remote repository.
一.如果需要push代码到码云,需要创建个人公钥,公共公钥只可以读不可以修改 二.执行代码即可:git push
- unity 如何打开本地文件夹,并选中文件
public static void OpenDirectory(string path, bool isFile = false) { if (string.IsNullOrEmpty(path)) ...
- Xcode中opengl的配置
1. GLUT + GLTools + SDL2 Frameworks Search Paths :Framework + Library ( $(PROJECT_DIR)/build ) Searc ...
- delphi uniDac
Delphi 2010安装及使用UniDAC 4.0 UniDAC是一个功能强大的非可视化跨数据库的数据访问组件,可用于Delphi,Delphi for .NET,C++Builder,and La ...
- (CSDN 迁移) JAVA循环删除List的某个元素
若列表中只可能存在一个则可以用简单的循环删除,不多说. 若列表中可能存在多个,尤其是可能有多个连续的需要删除,用简单循环有可能发生异常. 需要使用迭代器(Iterator),两种具体实现: 逻辑上是一 ...
- CentOS 7 编译安装clang+llvm
天在CentOS上将最新版本的LLVM套件(LLVM,Clang和Libc++)编译安装好了,中间遇到了不少问题.虽然已经有很多博客介绍如何编译安装LLVM了,但是根据我自己亲身体验的情况来看,还是有 ...
- Pycharm新建文件css文件无后缀,html中无法正确引入
使用pycharm新建了一个文件mycss,然后选择文件类型是css,显示也正常,但是在页面中使用link引入始终无法生效.后来加了后缀名.css,发现可以正常显示样式了,所以新建文件时最好就加上后缀 ...
- Linux Docker Introduction
Setup on Ubuntu. 前提条件: Docker需要两个重要的安装要求: 它仅适用于64位Linux安装,注意:是64位的Linux系统. 它需要Linux内核版本3.10或更高版本. 要查 ...
- SGU 127. Telephone directory --- 模拟
<传送门> 127. Telephone directory time limit per test: 0.25 sec. memory limit per test: 4096 KB C ...
- Linux内核--伙伴系统--页释放
本文转载自:http://www.cnblogs.com/tolimit/ 感觉原博分析的不错,借花献佛. ---------------------------------------------- ...