通常来讲,写完一个第三方库须要打包出三个文件夹的文件,对应三种不一样模块类型javascript
# outputpath ├── dist # umd module ├── es # es module ├── lib # commonjs module
UMD(Universal Module Definition)是 AMD 和 CommonJS 的糅合,跨平台的解决方案
;(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['A'] = factory() else root['A'] = factory() })(window, function() { //... })
CommonJS 模块是对象,是运行时加载,运行时才把模块挂载在 exports 之上(加载整个模块的全部),加载模块其实就是查找对象属性。
导出使用 module.exports,也能够 exports。就是在此对象上挂属性。exports 指向 module.exports,即 exports= module.exports
module.exports.add = function add() { return } exports.sub = function sub() { return } const a = require('a.js')
ES Module 不是对象,是使用 export 显示指定输出,再经过 import 输入。此法为编译时加载,编译时遇到 import 就会生成一个只读引用。等到运行时就会根据此引用去被加载的模块取值。因此不会加载模块全部方法,仅取所需。
export const m = 1 export { m } import { m } from 'a.js'
若是使用 webpack 来打包 umd 文件,咱们应该配置哪些选项html
const config = { entry, output: { path: './dist', libraryTarget: 'umd', filename: 'index.min.js', library: 'MyLibrary', libraryExport: 'default' }, externals: { react: { root: 'React', commonjs2: 'react', commonjs: 'react', amd: 'react' } } }
MyLibrary.default
才是咱们模块的返回值。经过设置libraryExport: 'default'
,起到MyLibrary = MyLibrary.default
的效果, 不须要再经过 default
属性去访问返回值// webpack 会判断不一样的环境,并以不一样的方式去访问react ;(function webpackUniversalModuleDefinition(root, factory) { if (typeof exports === 'object' && typeof module === 'object') module.exports = factory(require('react')) else if (typeof define === 'function' && define.amd) define(['react'], factory) else if (typeof exports === 'object') exports['MyLibrary'] = factory(require('react')) else root['MyLibrary'] = factory(root['React']) })
最后再配置一下 babel-loader,就能生成咱们指望的 umd 文件了java
使用 babel 打包就很简单了, 先看一下 babelrc 怎么写node
{ presets: [['@babel/env', { loose: true, modules: 'cjs' }], '@babel/preset-react'], plugins: [ ['@babel/plugin-transform-runtime', { useESModules: false }], ] }
loose
一句话解释: true 的时候代码更现代化代码量少,false 更兼容代码量也更多react
modules
设置使用不一样的模块类型,commonjs 的话,就设置成'cjs'webpack
babel 会给每一个编译的文件插入一些辅助方法,若是文件一多的话,就出现了不少重复代码,这个插件会改成从第三方包引用辅助方法,
须要额外安装@babel/runtime
git
e.g.github
var _interopRequireDefault = require('@babel/runtime/helpers/interopRequireDefault')
babel src --out-dir lib
只要把上面里全部 module 相关的设置改为 es module 就好了web
{ presets: [['@babel/env', { loose: true, modules: false }], '@babel/preset-react'], plugins: [ ['@babel/plugin-transform-runtime', { useESModules: true }], ] }
babel src --out-dir es
安利一波我的写的打包库的工具 build-my-package, js, ts都支持哦!:)shell