
构建工具前端【免费下载链接】brunch Web applications made easy. Since 2011.项目地址https://gitcode.com/gh_mirrors/br/brunch点击查看免费下载本文是 Brunch.io 官方指南见 packages/brunch-guide/content/fr/README.md系列的一部分聚焦如何将 Brunch 接入一个已存在的项目。如果你正从 Grunt、Gulp 或其他构建工具迁移而来面对的是一个早已成型的代码库而非按 Brunch 约定从零搭建的新项目那么本指南将围绕五个关键决策点展开源码在哪里、用什么语言、构建产物放哪里、源文件如何映射到目标文件、以及是否启用模块化包装。读完后你将能写出第一份真正服务于存量项目的brunch-config并理解paths、conventions、files、modules这些核心配置项在 Brunch 内部的真实运作方式。迁移前要回答的五个问题把 Brunch 交给一个既有项目之前先冷静回答以下五个问题它们分别对应brunch-config中的一组具体配置源码文件在哪里—— 决定paths.watched的值即 Brunch 要构建并监视的根目录集合。这些源码用什么语言编写—— 决定你需要安装哪些 Brunch 插件sass-brunch、stylus-brunch、jade-brunch 等。构建产物输出到哪个目录—— 决定paths.public的值。源文件到目标文件的映射关系是什么—— 决定files配置中javascripts、stylesheets、templates三个小节的结构与joinTo规则。要不要把应用 JS 包装成模块—— 决定modules.wrapper与modules.definition的设置。下面逐一深入。问题一源码在哪 ——paths.watched与相关约定paths.watched用于描述构建所依赖的根路径集合。其默认值为[app, test, vendor]见 lib/utils/config-validate.js 中的 schema 定义但绝大多数存量项目都需要显式修改它——你的源码可能分布在src/、lib/或若干个平级目录中而默认的app目录根本不存在。围绕源码位置还有两个conventions配置需要一并考虑conventions.assets指定哪些目录下的文件会被原样复制copy-paste到输出目录而不经过任何编译或打包。默认匹配规则为/assets\//见 lib/utils/config-validate.js也就是说任何路径中包含assets/的文件都会被当作静态资源直接搬运。conventions.vendor指定哪些目录中的 JS不应被包装成模块默认匹配规则为/(^node_modules|vendor)\//见 lib/utils/config-validate.js。需要注意如果通过 Bower 引入组件Brunch 对这些组件永远不做模块包装即使它们不在vendor目录中。从实现上看这两条约定在配置加载时会被归一化为可复用的判定函数。在 lib/utils/config.js 的normalizeConfig中每个约定都通过anymatch编译成conventions[key]检查器其中vendor约定直接使用该检查器而其他约定则额外排除了 npm 包路径!deppack.isNpm(path) fn(path)。这些检查器随后被 lib/fs_utils/file_list.js 用来决定一个文件被归入assets静态资源还是files源码并最终决定其是否参与模块包装。示例假设你的存量项目源码放在src/第三方库在lib/third_party/// brunch-config.js module.exports { paths: { watched: [src, lib/third_party] }, conventions: { assets: /assets\//, vendor: /third_party\// } };问题二用什么语言 —— 按需混装插件问题二决定你需要哪些Brunch 插件。核心思想是同一类源码可以混用多种语言及其插件。例如使用 Bootstrap 时作者倾向于直接用它的 SASS 源码这样可以通过修改_variables.scss轻松定制主题而自己的样式则偏爱 Stylus于是sass-brunch与stylus-brunch常常同时安装、同时工作。如果应用采用客户端 MVC 架构通常会把模板独立成文件这时可用jade-brunch或dust-linkedin-brunch之类的模板插件把模板透明地编译成导出唯一渲染函数的模块——该函数接收一个 presenter即 view model对象作为参数并同步返回 HTML 字符串。插件混装之所以可行源于 Brunch 的管道式编译设计。在 lib/fs_utils/pipeline.js 中nextCompiler会按compiler.pattern依次匹配文件路径并逐个调用compiler.compile(file)直到没有插件能处理为止换言之多个编译器可以串联作用于同一份源码也可以按路径各司其职。每种源码类型如sass、stylus、jade对应一个实现了compile方法、声明了pattern的插件对象。问题三构建产物输出到哪 ——paths.publicpaths.public指定构建产物的输出目录默认值为public见 lib/utils/config-validate.js。有两点值得注意该目录不必在构建前存在Brunch 在写出文件时会自动创建目录见 lib/fs_utils/generate.js 中writeFile对父目录的递归创建逻辑。所有目标文件路径即joinTo的键都是相对于paths.public解析的。从源码看lib/utils/config.js 中的setConfigDefaults会把paths.public与paths.root拼接成绝对路径并将其同步到config.server.publicPath保证内置服务器在overrides生效后仍指向正确的输出目录见 lib/utils/config.js。问题四源到目标的映射 ——files与joinTofiles配置是迁移中最核心、最灵活的部分最多包含三个小节javascripts所有最终产出为 JS 的文件模板预编译除外stylesheets所有最终产出为 CSS 的文件templates所有模板预编译产物——每个模板被预编译成一个渲染函数接收 presenterview model对象、返回 HTML通常其目标与javascripts的核心目标相同。每个小节至少包含一个joinTo属性。joinTo的值可以非常简单也可以相当高级形式一单个字符串如果只提供一个文件路径字符串该小节所有候选文件都会被拼接到这一个文件中files: { stylesheets: { joinTo: stylesheets/app.css } }形式二对象多目标 过滤如果提供一个对象则键是目标文件路径值是 anymatch 匹配集用于决定哪些源文件进入哪个目标。匹配值可以是类型说明示例String精确匹配 Brunch 眼中的文件路径见下文模块名从哪来对路径形态的说明app/init.js正则表达式匹配文件路径特别适合路径前缀/^app\//、/^vendor\//谓词函数接收精确路径同步返回布尔值决定是否收录path path.endsWith(.coffee)数组上述任意类型的混合[app/, /^vendor\//]下面是一个真实项目Chaplain 骨架的完整示例见 packages/skeletons/brunch-with-chaplin-js/brunch-config.jsexports.config { files: { javascripts: { joinTo: { javascripts/app.js: /^app/, javascripts/vendor.js: /^(?!app)/ } }, stylesheets: { joinTo: stylesheets/app.css }, templates: { joinTo: javascripts/app.js } } };可以看到javascripts被拆成app.js以app开头的文件与vendor.js其余文件两个目标templates与核心 JS 共享同一个目标javascripts/app.jsstylesheets则使用最简单的字符串形式。从源码看joinTo在配置加载时会被统一归一化。在 lib/utils/config.js 的normalizeJoinConfig中字符串形式的joinTo会被转换为{[目标路径]: () true}即所有文件都进这一个目标对象形式则对每个目标值调用anymatch(checker)编译成匹配函数。此外lib/utils/config.js 中的createJoinConfig还隐含一条规则如果javascripts定义了joinTo而templates没有定义templates会自动继承javascripts.joinTo——这正是上面示例中模板可以省略、也可以显式写出同一个目标的底层原因。还有一个补充机制值得一提config.files.javascripts.entryPoints可以把joinTo视为一种入口点的特殊情形让某个入口文件单独打包见 lib/utils/config.js但入口文件必须位于paths.watched之内否则会报错。问题五要不要模块化 ——modules.wrapper与modules.definition第五个问题在作者看来根本不该是问题当然要用模块。默认情况下 Brunch 采用CommonJS这既便于编写同构 JS也为日后迁移到原生 ES6 模块铺路。模块化由两个配置联合控制默认值见 lib/utils/config-validate.jsmodules.wrapper决定单个源文件如何被包装成模块默认commonjsmodules.definition决定模块系统的运行时定义代码如何注入输出文件默认commonjs。可用的取值取值效果commonjs默认每个模块被包装为require.register(模块名, function(exports, require, module) { ... });并在输出头部注入 CommonJS 的 require 定义false关闭包装/定义文件内容原样输出——适合想回到石器时代的纯拼接场景amd使用 AMD 模块包装自定义函数为更小众的模块系统提供完全定制化的包装与定义逻辑从源码看lib/utils/modules.js 中的getWrapperFn明确给出了commonjs与false两种内置包装器的实现前者生成require.register(...)的前缀与后缀后者直接返回原数据即不包装。normalizeWrapper还会先对路径做规范化再调用nameCleaner得到最终模块名lib/utils/modules.js。运行时定义则由 lib/utils/modules.js 的normalizeDefinition决定commonjs返回commonjs-require-definition包见 packages/subdependencies/commonjs-require-definition/require.jsfalse则返回空字符串。需要提醒的是模块包装只对非 vendor、非 helper的 JS 生效。在 lib/fs_utils/source_file.js 中_shouldBeWrapped要求文件isJS !isVendor换言之命中conventions.vendor的文件即使开启了 CommonJS 也不会被包装。模块名从哪来 —— 默认命名算法与nameCleaner使用模块化后最后一个重要话题是模块名。默认情况下 Brunch 的模块命名算法分三步取文件相对于监视根目录的精确路径例如app/application.js去掉扩展名得到app/application如果只有一个参与模块包装的监视路径默认只有app则去掉该前缀得到application但如果存在多个参与包装的监视路径前缀会保留。如果你不满意默认命名可以通过modules.nameCleaner提供一个自定义的模块名计算函数。默认的nameCleaner实现是path path.replace(/^app\//, )见 lib/utils/config-validate.js与上述第三步的行为完全吻合。实战示例保留长文件名、输出短模块名假设你的存量项目把第三方库放在app/externals/目录文件名携带版本与语言信息如jquery-1.11.2-min.js、moment-2.2.1-fr.js但你希望模块名保持简洁通用如jquery、moment。此时可以在brunch-config.js中这样写module.exports { modules: { nameCleaner(path) { return path // 去掉 app/ 与 app/externals/ 前缀 .replace(/^app\/(?:externals\/)?/, ) // 去掉形如 -1.11.2 的版本号后缀 .replace(/-\d(?:\.\d)/, ) // 把 -fr. 语言后缀处理成 . .replace(-fr., .) } } };这个函数的输入正是从监视根目录开始的相对路径 扩展名它在 lib/utils/config.js 的normalizeConfig中被传入wrappers.normalizeWrapper并在 lib/utils/modules.js 中应用于每一个被包装的模块路径最终出现在require.register(jquery, ...)的模块名位置上。验证与调试配置加载路径一览理解上述配置如何进入运行时有助于排查迁移中的问题。在 lib/utils/config.js 的loadConfig中完整流程大致是读取项目根目录的package.json按优先级加载配置package.json中的brunch字段 →brunch-config.js→ 默认配置见tryToLoadlib/utils/config.js用 skemata schema 校验配置并填充默认值见 lib/utils/config-validate.js应用overrides按NODE_ENV/BRUNCH_ENV等环境切换例如 test/fixtures/config-with-overrides.js 展示了按环境切换paths.public的用法对应测试见 test/config.js归一化joinTo与conventions生成config._normalized加载插件并开始构建。迁移存量项目时若发现文件没有按预期进入某个目标优先检查三处paths.watched是否覆盖了真实源码目录、conventions.vendor是否误伤了应参与包装的文件、以及joinTo的正则是否与实际路径形态相对监视根目录吻合。小结将 Brunch 接入存量代码库本质上就是用一份brunch-config明确回答五个问题源码位置paths.watched、语言与插件sass-brunch、stylus-brunch、jade-brunch等、输出目录paths.public、源到目标的映射files.javascripts/files.stylesheets/files.templates及joinTo的字符串、正则、函数、数组四种匹配形式、以及模块化策略modules.wrapper/modules.definition/modules.nameCleaner。这五组配置的组合能力足以让 Brunch 在不重构既有目录结构的前提下接管任何历史项目的构建而joinTo的 anymatch 匹配与模块名的自定义清洗则是让迁移过程既保目录原貌、又得模块整洁的两个关键杠杆。「上一篇模板初体验 • 下一篇开发与生产构建」赞分享构建工具前端【免费下载链接】brunch Web applications made easy. Since 2011.项目地址https://gitcode.com/gh_mirrors/br/brunch点击查看免费下载相关推荐Terratest v2 导入路径迁移完全指南import map 全量映射表与源码级解读Terratest v2 导入路径迁移完全指南import map 全量映射表与源码级解读 Terratest v2 将原本单一的 github.com/gr测试开发工具DevOps质量保障未来已来ElasticDL与DLRover的技术演进与自动扩展训练展望未来已来ElasticDL与DLRover的技术演进与自动扩展训练展望 在当今AI大模型时代分布式深度学习训练已成为技术发展的必然趋势。 ElasticDL大模型人工智能NLP本地部署微调模型推理服务notepad-- 代码折叠3 步把 5000 行文件折成一张目录notepad 代码折叠3 步把 5000 行文件折成一张目录 周一 9:40你盯着一份 4800 行的 .cpp 文件滚轮翻了 20 分钟回答不出一个桌面应用上一篇IDM激活脚本完整使用教程如何永久免费使用Internet Download Manager下一篇终极指南Tachyon多项式乘法优化中NTT与Karatsuba算法的性能对比创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考