能否用RequireJS构建包含CDN插件的单文件优化输出?
解决RequireJS构建时"Cannot read property 'normalize' of undefined"错误
先还原你的场景细节:
代码文件
main.js
requirejs.config({ css: "https://cdnjs.cloudflare.com/ajax/libs/require-css/0.1.10/css", fontawesome: "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome" }); requirejs(["css!fontawesome"]);
app.build.js
({ name: "main", out: "built.js", paths: { css: "empty:", fontawesome: "empty:" } })
错误信息
执行命令 r.js -o app.build.js 时抛出:
Error: TypeError: Cannot read property 'normalize' of undefined In module tree: main
问题原因
这个错误的核心很明确:你把css插件模块标记为了empty:,但RequireJS在构建时处理css!fontawesome这个依赖时,必须调用css插件的normalize方法来解析带插件前缀的模块ID。当css被设为empty:后,RequireJS找不到这个关键方法,自然会抛出报错。
解决方案
你需要调整构建配置,确保css插件在构建过程中能被正常访问,同时只排除fontawesome资源:
方案1:保留css插件路径,仅标记fontawesome为empty
建议先把require-css插件下载到本地项目中(避免构建时依赖CDN网络稳定性),然后修改app.build.js:
({ name: "main", out: "built.js", paths: { // 指向本地的require-css插件文件,示例为放在lib目录下 css: "lib/css", fontawesome: "empty:" } })
如果不想把css插件打包到最终的built.js里,可以加上stubModules选项——它会把指定模块替换为带必要接口(比如normalize)的空存根:
({ name: "main", out: "built.js", paths: { css: "lib/css", fontawesome: "empty:" }, stubModules: ['css'] })
方案2:用modules数组精确控制依赖
如果项目结构更复杂,可通过modules数组指定要打包的模块和排除的依赖:
({ name: "main", out: "built.js", paths: { css: "lib/css", fontawesome: "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome" }, modules: [ { name: "main", exclude: ["fontawesome"] } ] })
关于你的疑问:exclude仅对模块生效?
完全正确!exclude选项确实主要针对标准JS模块(即通过define定义的模块)。对于css!fontawesome这种由插件加载的非JS资源,exclude无法直接识别处理——这类资源的加载逻辑完全依赖对应的插件(这里是css插件)。所以处理这类资源时,需要结合插件特性和构建配置,比如用empty:标记外部资源,或者通过插件专属配置来排除。
内容的提问来源于stack exchange,提问作者Oscar Gardiazabal
相关产品推荐
相关产品推荐

