一张图呈现前端模块演化历史

2020-05-28 17:00:57 浏览数 (1)

在模块化编程中,开发者将程序分解成离散功能块(discrete chunks of functionality),并称之为模块。 精心编写的模块提供了可靠的抽象和封装界限,使得应用程序中每个模块都具有条理清楚的设计和明确的目的。

webpack 模块定义

代码语言:javascript复制
output: {
  library: "MyLibrary",
  libraryTarget: "umd"
}

输出内容(不同版本的webpack略有差异,内容相符):

代码语言:javascript复制
(function webpackUniversalModuleDefinition(root, factory) {
  if(typeof exports === 'object' && typeof module === 'object')
    module.exports = factory();
  else if(typeof define === 'function' && define.amd)
    define([], factory);
  else if(typeof exports === 'object')
    exports["MyLibrary"] = factory();
  else
    root["MyLibrary"] = factory();
})(typeof self !== 'undefined' ? self : this, function() {
  return _entry_return_; // 此模块返回值,是入口 chunk 返回的值
});

也可针对不同模式指定不同名称

代码语言:javascript复制
output: {
  library: {
    root: "MyLibrary",
    amd: "my-library",
    commonjs: "my-common-library"
  },
  libraryTarget: "umd"
}

webpack 模块解析

代码语言:javascript复制
import foo from 'path/to/module'
// 或者
require('path/to/module')

webpack 使用 enhanced-resolve 来解析文件路径(转换为模块的绝对路径)。

引子:如何处理图片的
代码语言:javascript复制
import logo from '@/assets/images/logo.png'
代码语言:javascript复制
// webpack.config.js
{
  test: /.(png|jpe?g|gif|webp)(?.*)?$/,
  	use: [{
		loader: 'url-loader',
	    options: {
	    	limit: 4096,
	       	fallback: {
	         	loader: 'file-loader',
	         	options: { name: 'img/[name].[hash:8].[ext]' }
	       	}
		}
   }]
}

file-loader:将文件上的 import / require() 解析为url,并输出到输出目录并返回 public URL。 该图像将被处理并添加到 output 目录,并且 logo 变量将包含该图像在处理后的最终 url name: 'img/[name].[hash:8].[ext]' => /img/logo.b4d70ee2.png PS:url-loader 功能类似于 file-loader,但是在文件大小(单位 byte)低于指定的限制时,可以返回一个 DataURL。

对于 css 或 html 中引入,处理方式类似!

代码语言:javascript复制
background-url: url('../assets/images/logo.png') 
代码语言:javascript复制
<img class="logo" src="../assets/images/logo.png" alt />

css-loader/html-loader 会识别这是一个本地文件,并将 '../assets/images/logo.png' 路径,替换为 output 目录中图像的最终路径。

vue-loader: <img src="../image.png"> 将会被编译成为 createElement('img', { attrs: { src: require('../image.png') // 现在这是一个模块的请求了 } })

默认情况下,每个本地的 <img src="image.png"> 都需要通过 require (require('./image.png'))来进行加载。

代码语言:javascript复制
 <img class="logo" :src="require('@/assets/images/logo.png')" alt />
绝对路径

直接使用,不需要进一步再做解析

相对路径

import/require 中给定的相对路径,会添加此上下文路径(context path),以产生模块的绝对路径(absolute path)

模块路径
代码语言:javascript复制
import "module"
import "module/lib/file"

模块将在 resolve.modules 中指定的所有目录内搜索。 你可以替换初始模块路径,此替换路径通过使用 resolve.alias 配置选项来创建一个别名。

一旦根据上述规则解析路径后,解析器(resolver)将检查路径是否指向文件或目录。

如果路径指向一个文件:

  • 具有文件扩展名,则直接将文件打包
  • 否则,将使用 [resolve.extensions] 选项作为文件扩展名来解析

如果路径指向一个文件夹:

  • 如果文件夹中包含 package.json 文件,则按照顺序查找 resolve.mainFields 配置选项中指定的字段;
    • target 属性设置为 webworkerweb 或者没有指定,默认值为: mainFields: ["browser", "module", "main"]
    • 对于其他任意的 target(包括 node),默认值为: mainFields: ["module", "main"]

    设置 target,target 同时支持 function module.exports = { target: 'node' } target 选项 描述 async-node 编译为类 Node.js 环境可用(使用 fs 和 vm 异步加载分块) electron-main 编译为 Electron 主进程 electron-renderer 编译为 Electron 渲染进程,使用 JsonpTemplatePlugin, FunctionModulePlugin 来为浏览器环境提供目标,使用 NodeTargetPlugin 和 ExternalsPlugin 为 CommonJS 和 Electron 内置模块提供目标 node 编译为类 Node.js 环境可用(使用 Node.js require 加载 chunk) node-webkit 编译为 Webkit 可用,并且使用 jsonp 去加载分块。支持 Node.js 内置模块和 nw.gui 导入(实验性质) web 编译为类浏览器环境里可用(默认) webworker 编译成一个 WebWorker

  • 如果 package.json 文件不存在或者 package.json 文件中的 main 字段没有返回一个有效路径,则按照顺序查找 resolve.mainFiles (解析目录时要使用的文件名。默认:mainFiles: ["index"])配置选项中指定的文件名
  • 文件扩展名通过 resolve.extensions 选项采用类似的方法进行解析

0 人点赞