现代前端开发离不开打包工具,以 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模块组织关系的更多相关文章

  1. React系列文章:Webpack模块组织关系

    现代前端开发离不开打包工具,以Webpack为代表的打包工具已经成为日常开发必备之利器,拿React技术栈为例,我们ES6形式的源代码,需要经过Webpack和Babel处理,才能生成发布版文件,在浏 ...

  2. 部署React+webpack工程的步骤

    # 部署React+webpack工程的步骤ps:以Mac os系统做开发环境.因为npm现在使用灰常的慢,所以我使用淘宝境像cnpm. 1,准备工作: 先确保存已经安装了node.js: 2,文件部 ...

  3. react webpack.config.js 入门学习

    在学习react 的时候必然会用到webpack打包工具,webpack的快速入门另外一篇文章中有记录,这里只记录webpack.config.js文件,因为每个项目下都必须配置,通俗的讲,它的作用就 ...

  4. 真刀实战地搭建React+Webpack+Express搭建一个简易聊天室

    一.前面bb两句 因为自惭(自残)webpack配置还不够熟悉,想折腾着做一个小实例熟悉.想着七夕快到了,做一个聊天室自己和自己聊天吧哈哈.好了,可以停止bb了,说一下干货. 二. 这个项目能学到啥? ...

  5. react常用模块介绍

    react各个模块: 1.node.js自带的模块(原生模块):https://www.jianshu.com/p/abc72267abfc原生模块的api文档地址:http://nodejs.cn/ ...

  6. React + webpack 环境配置

    安装配置Babel babel-preset-es2015 ES6语法包,使代码可以随意地使用ES6的新特性. babel-preset-react React语法包,专门用于React的优化,在代码 ...

  7. 每天记录一点:NetCore获得配置文件 appsettings.json vue-router页面传值及接收值 详解webpack + vue + node 打造单页面(入门篇) 30分钟手把手教你学webpack实战 vue.js+webpack模块管理及组件开发

    每天记录一点:NetCore获得配置文件 appsettings.json   用NetCore做项目如果用EF  ORM在网上有很多的配置连接字符串,读取以及使用方法 由于很多朋友用的其他ORM如S ...

  8. 用React & Webpack构建前端新闻网页

    这是一篇给初学者的教程, 在这篇教程中我们将通过构建一个 Hacker News 的前端页面来学习 React 与 Webpack. 它不会覆盖所有的技术细节, 因此它不会使一个初学者变成大师, 但希 ...

  9. scss + react + webpack + es6

    scss + react + webpack + es6 写在前面: 刚学习完慕课网里的一个幻灯片案例,自己加了刚学的react,两者结合.首先让大家看看效果 点击此处 你可以先用纯js实现上面的效果 ...

随机推荐

  1. xpath和contains模糊匹配

    xpath可以以标签定位,也可以@任意属性: 如:以input标签定位:driver.find_element_by_xpath("//input[@id='kw']") 如:@t ...

  2. (原)理解码率控制模式(x264,x265,vpx)

    理解码率控制模式(x264,x265,vpx) 原文链接:https://slhck.info/video/2017/03/01/rate-control.html 翻译:lihaiping1603@ ...

  3. 拼接Sql语句小心得

    在往数据库插入数据时,需要根据数据和数据库中的列信息进行拼接,在本篇文章中,输出小心得.使用语言为 python. 拼接原始列信息 比如待插入数据库列信息为 deptNo,dName, Locate, ...

  4. ThinkPHP5远程代码执行高危漏洞(附:升级修复解决方法)

    漏洞描述 由于ThinkPHP5框架对控制器名没有进行足够的安全检测,导致在没有开启强制路由的情况下,黑客构造特定的请求,可直接GetWebShell. 漏洞评级 严重 影响版本 ThinkPHP 5 ...

  5. myeclipse An internal error occurred during: "Initialize metrics".

    重新安装的myeclipse,在打开的时候弹出:    An internal error occurred during: "Initialize metrics". com/g ...

  6. 【ARM-Linux开发】OpenACC并行编程实战笔记

    今年运气比较好,学了cuda之后,了解到了gpu的另两种使用语言opencl和openacc,  opencl(Open Computing Language ,开放计算语言)是面向异构系统的并行编程 ...

  7. 解决angular+element原有组件样式不能覆盖element自带样式问题

    在对应的组件中写入 ::ng-deep   +     想要改变的element组件样式名即可

  8. 在ensp上配置RIPv2的认证

    原理 实验模拟 实验拓扑 测试连通性 搭建rip网络 查看路由表 R3模拟攻击首先把在自己的的ip通告网段 配置完成后查看一下路由表 可以看到已经非法获取R1R2的网段信息,那么现在我们R3可以向两个 ...

  9. aspnetcore identity result.Succeeded SignInManager.IsSignedIn(User) false?

    登陆返回的是 result.Succeeded 为什么跳转到其他页面SignInManager.IsSignedIn(User)为false呢? result.Succeeded _signInMan ...

  10. pyhthon Opencv截取视频中的图片

    import os import cv2 ##加载OpenCV模块 def video2frames(pathIn='', pathOut='', imgname='', only_output_vi ...