{"id":15893847,"url":"https://github.com/chinanf-boy/microbundle-explain","last_synced_at":"2025-04-02T18:16:16.762Z","repository":{"id":90548454,"uuid":"120885512","full_name":"chinanf-boy/microbundle-explain","owner":"chinanf-boy","description":"explain : microbundle 0 config  bundler for tiny modules. 0配置构建小模块 power by rollup","archived":false,"fork":false,"pushed_at":"2018-02-09T09:28:55.000Z","size":7,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-08T08:47:13.737Z","etag":null,"topics":["bundle","explain","microbundle","rollup"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chinanf-boy.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-02-09T09:28:44.000Z","updated_at":"2018-02-09T09:29:41.000Z","dependencies_parsed_at":null,"dependency_job_id":"c7eae374-d1a2-4d9c-afbe-65be5fd84a50","html_url":"https://github.com/chinanf-boy/microbundle-explain","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chinanf-boy%2Fmicrobundle-explain","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chinanf-boy%2Fmicrobundle-explain/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chinanf-boy%2Fmicrobundle-explain/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chinanf-boy%2Fmicrobundle-explain/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chinanf-boy","download_url":"https://codeload.github.com/chinanf-boy/microbundle-explain/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246866100,"owners_count":20846496,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bundle","explain","microbundle","rollup"],"created_at":"2024-10-06T08:13:54.138Z","updated_at":"2025-04-02T18:16:16.737Z","avatar_url":"https://github.com/chinanf-boy.png","language":"JavaScript","readme":"# microbundle\n\n由`Rollup`提供支持的小型模块的零配置打包程序。by [developit](https://github.com/developit)\n\n[![explain](http://llever.com/explain.svg)](https://github.com/chinanf-boy/Source-Explain)\n    \nExplanation\n\n\u003e \"version\": \"1.0.0\"\n\n[github source](https://github.com/developit/microbundle)\n\n~~[english](./README.en.md)~~\n\n---\n\n懒惰才能使人进步😊\n\n---\n\n## 目录\n\n---\n\n## 使用\n\n``` js\nmicrobundle\n// \nmicrobundle build\n```\n\n默认情况下, 会在项目根目录-package.json- `main` 字样, 当然你也可以指定\n\n\u003e 你可以看看作者对 此项目-microbundle 的[使用项目-greenlet](https://github.com/developit/greenlet/blob/master/package.json#L10)\n\n\u003e 更可以看看-[greenlet-explain](https://github.com/chinanf-boy/greenlet-explain)\n\n---\n\n## package\n\n``` js\n  \"main\": \"dist/microbundle.js\", // 构建的\n  \"source\": \"src/index.js\", // 源码\n  \"bin\": \"dist/cli.js\", // 终端命令\n```\n\n## cli\n\n既然💪-microbundle-💪 是通过\n`microbundle` 启动构建的\n\n我们自然从命令代码开始\n\n``` js\n#!/usr/bin/env node\n\nimport sade from 'sade'; // 命令解析\nimport microbundle from '.';\n\nlet { version } = require('../package');\nlet prog = sade('microbundle');\n\nlet toArray = val =\u003e Array.isArray(val) ? val : val == null ? [] : [val];\n// 变 数组\n\nprog\n\t.version(version)\n\t.option('--entry, -i', 'Entry module(s)')\n\t.option('--output, -o', 'Directory to place build files into')\n\t.option('--format, -f', 'Only build specified formats', 'es,cjs,umd')\n\t.option('--target', 'Specify your target environment', 'node')\n\t.option('--external', `Specify external dependencies, or 'all'`)\n\t.option('--compress', 'Compress output using UglifyJS', true)\n\t.option('--strict', 'Enforce undefined global context and add \"use strict\"')\n\t.option('--name', 'Specify name exposed in UMD builds')\n\t.option('--cwd', 'Use an alternative working directory', '.');\n\n// 第一个变量 命令选项 第二个变量 说明 第三个变量 默认值\n\nprog\n\t.command('build [...entries]', '', { default: true })\n\t.describe('Build once and exit')\n\t.action(run);\n\nprog\n\t.command('watch [...entries]')\n\t.describe('Rebuilds on any change')\n\t.action((str, opts) =\u003e run(str, opts, true));\n\n// Parse argv; add extra aliases\nprog.parse(process.argv, {\n\talias: {\n\t\to: ['output', 'd'],\n\t\ti: ['entry', 'entries', 'e']\n\t}\n});\n\n// 这个命令解析库-api-其实都挺好懂的\n\n// 主要是 run \n\nfunction run(str, opts, isWatch) {\n\topts.watch = !!isWatch;\n\topts.entries = toArray(str || opts.entry).concat(opts._);\n\tmicrobundle(opts) // 用 sade 解析来的命令给予 microbundle\n\t\t.then( output =\u003e {\n            if (output!=null) process.stdout.write(output + '\\n');\n            // 把有色的结果-输出终端\n\t\t\tif (!opts.watch) process.exit(0);\n\t\t})\n\t\t.catch(err =\u003e {\n            process.stderr.write(String(err) + '\\n');\n            // 把有色的结果-输出终端            \n\t\t\tprocess.exit(err.code || 1);\n\t\t});\n}\n\n```\n## index\n\n我们先直入主题 [`microbundle`](#microbundle-async) | [从头开始-代码1](#导入)\n\n### 导入\n\n代码 1- 22\n\n``` js\nimport 'acorn-jsx';\nimport fs from 'fs';\nimport { resolve, relative, dirname, basename, extname } from 'path';\nimport chalk from 'chalk'; // 终端-有色-输出\nimport { map, series } from 'asyncro';\nimport promisify from 'es6-promisify';\nimport glob from 'glob';\nimport autoprefixer from 'autoprefixer';\nimport { rollup, watch } from 'rollup';\nimport nodent from 'rollup-plugin-nodent';\nimport commonjs from 'rollup-plugin-commonjs';\nimport nodeResolve from 'rollup-plugin-node-resolve';\nimport buble from 'rollup-plugin-buble';\nimport uglify from 'rollup-plugin-uglify';\nimport postcss from 'rollup-plugin-postcss';\nimport alias from 'rollup-plugin-strict-alias';\nimport gzipSize from 'gzip-size';\nimport prettyBytes from 'pretty-bytes';\nimport shebangPlugin from 'rollup-plugin-preserve-shebang';\nimport typescript from 'rollup-plugin-typescript';\nimport flow from './lib/flow-plugin';\nimport camelCase from 'camelcase';\n```\n\n### index-变量\n\n``` js\nconst readFile = promisify(fs.readFile);\nconst stat = promisify(fs.stat);\nconst isDir = name =\u003e stat(name).then( stats =\u003e stats.isDirectory() ).catch( () =\u003e false );\nconst isFile = name =\u003e stat(name).then( stats =\u003e stats.isFile() ).catch( () =\u003e false );\nconst removeScope = name =\u003e name.replace(/^@.*\\//, '');\nconst safeVariableName = name =\u003e camelCase(removeScope(name).toLowerCase().replace(/((^[^a-zA-Z]+)|[^\\w.-])|([^a-zA-Z0-9]+$)/g, ''));\n\nconst WATCH_OPTS = {\n\texclude: 'node_modules/**'\n};\n```\n\n### microbundle-async\n\n定义-异步-主函数\n\n代码 35-135\n\n``` js\nexport default async function microbundle(options) {\n\tlet cwd = options.cwd = resolve(process.cwd(), options.cwd), // 命令路径\n\t\thasPackageJson = true;\n\n\ttry {\n\t\toptions.pkg = JSON.parse(await readFile(resolve(cwd, 'package.json'), 'utf8')); // 路径中的 - package.json - 文件\n\t}\n\tcatch (err) {\n\t\tprocess.stderr.write(chalk.yellow(`${chalk.yellow.inverse('WARN')} no package.json found. Assuming a name of \"${basename(options.cwd)}\".`)+'\\n');\n\t\tlet msg = String(err.message || err);\n\t\tif (!msg.match(/ENOENT/)) console.warn(`  ${chalk.red.dim(msg)}`);\n\t\toptions.pkg = {};\n\t\thasPackageJson = false;\n\t}\n\n\tif (!options.pkg.name) {\n\t\toptions.pkg.name = basename(options.cwd); // 项目名\n\t\tif (hasPackageJson) {\n\t\t\tprocess.stderr.write(chalk.yellow(`${chalk.yellow.inverse('WARN')} missing package.json \"name\" field. Assuming \"${options.pkg.name}\".`)+'\\n');\n\t\t}\n\t}\n\n\tconst jsOrTs = async filename =\u003e resolve(cwd, `${filename}${await isFile(resolve(cwd, filename+'.ts')) ? '.ts' : '.js'}`);\n    // 是 js 还是 ts 文件\n    options.input = [];\n    \n\t[].concat(\n\t\toptions.entries \u0026\u0026 options.entries.length ? options.entries : options.pkg.source || (await isDir(resolve(cwd, 'src')) \u0026\u0026 await jsOrTs('src/index')) || await jsOrTs('index') || options.pkg.module\n\t).map( file =\u003e glob.sync(resolve(cwd, file)) ).forEach( file =\u003e options.input.push(...file) );\n    \n    //  从 定义的目录 or 文件 或 默认中找出-入口文件\n\n\n    let main = resolve(cwd, options.output || options.pkg.main || 'dist');\n    \n    // 输出位置|文件-初始化\n\n\tif (!main.match(/\\.[a-z]+$/) || await isDir(main)) {\n        // 当 main不符合文件名规范 或者 是目录\n        main = resolve(main, `${removeScope(options.pkg.name)}.js`);\n        // 重定义-输出文件\n    }\n\n    \n\toptions.output = main;\n\n\tlet entries = (await map([].concat(options.input), async file =\u003e {\n\t\tfile = resolve(cwd, file);\n\t\tif (await isDir(file)) {\n\t\t\tfile = resolve(file, 'index.js');\n\t\t}\n\t\treturn file; // 加入目录\n\t})).filter( (item, i, arr) =\u003e arr.indexOf(item)===i ); // 去掉多余\n\n\toptions.entries = entries;\n\n\toptions.multipleEntries = entries.length\u003e1;\n\n\tlet formats = (options.format || options.formats).split(','); // 是否有-构建输出文件类型-要求\n    // always compile cjs first if it's there:\n    // 总是构建 cjs 类型 优先\n\tformats.sort( (a, b) =\u003e a==='cjs' ? -1 : a\u003eb ? 1 : 0);\n\n\tlet steps = [];\n\tfor (let i=0; i\u003centries.length; i++) {\n\t\tfor (let j=0; j\u003cformats.length; j++) {\n            steps.push(createConfig(options, entries[i], formats[j], i===0 \u0026\u0026 j===0));\n            // 根据每个入口文件, 每个输出类型\n            // 带配置-\u003e一步一步添加\n\t\t}\n\t}\n\n```\n\n- [createConfig 配置好 rollup构建所需配置](./createConfig.readme.md)\n\n---\n\n``` js\n\tasync function getSizeInfo(code, filename) {\n\t\tlet size = await gzipSize(code);\n\t\tlet prettySize = prettyBytes(size);\n\t\tlet color = size \u003c 5000 ? 'green' : size \u003e 40000 ? 'red' : 'yellow';\n        return `${' '.repeat(10-prettySize.length)}${chalk[color](prettySize)}: ${chalk.white(basename(filename))}`;\n        // 显示-文件大小\n\t}\n\n\tif (options.watch) { // 监听\n\t\tconst onBuild = options.onBuild;\n\t\treturn new Promise( (resolve, reject) =\u003e {\n\t\t\tprocess.stdout.write(chalk.blue(`Watching source, compiling to ${relative(cwd, dirname(options.output))}:\\n`));\n\t\t\tsteps.map( options =\u003e {\n\t\t\t\twatch(Object.assign({\n\t\t\t\t\toutput: options.outputOptions,\n\t\t\t\t\twatch: WATCH_OPTS\n\t\t\t\t}, options.inputOptions)).on('event', e =\u003e {\n\t\t\t\t\tif (e.code==='ERROR' || e.code==='FATAL') {\n\t\t\t\t\t\treturn reject(e);\n\t\t\t\t\t}\n\t\t\t\t\tif (e.code==='END') {\n\t\t\t\t\t\tgetSizeInfo(options._code, options.outputOptions.file).then( text =\u003e {\n\t\t\t\t\t\t\tprocess.stdout.write(`Wrote ${text.trim()}\\n`);\n\t\t\t\t\t\t});\n\t\t\t\t\t\tif (typeof onBuild=='function') {\n\t\t\t\t\t\t\tonBuild(e);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t});\n\t\t});\n\t}\n\n```\n\n---\n\n``` js\n\tlet cache;\n\tlet out = await series(steps.map( ({ inputOptions, outputOptions }) =\u003e async () =\u003e {\n\t\tinputOptions.cache = cache;\n\t\tlet bundle = await rollup(inputOptions); // 入口配置\n\t\tcache = bundle;\n\t\tawait bundle.write(outputOptions); // 写 输出\n        return await getSizeInfo(bundle._code, outputOptions.file);\n        // 显示-文件大小, 并返回-颜色字符\n\t}));\n\n\n    return chalk.blue(`Build output to ${relative(cwd, dirname(options.output)) || '.'}:`) + '\\n   ' + out.join('\\n   ');\n    // 颜色记录\n}\n```","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchinanf-boy%2Fmicrobundle-explain","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchinanf-boy%2Fmicrobundle-explain","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchinanf-boy%2Fmicrobundle-explain/lists"}