【问题标题】:How do you modularize your Chrome Applications with Browserify?您如何使用 Browserify 模块化您的 Chrome 应用程序?
【发布时间】:2013-01-28 22:30:50
【问题描述】:

我观看了以下Google Apps Office video 并了解了如何使用 browserify 使用 node CommonJS 打包系统将您的 JS 打包到一个文件中。我喜欢这个想法,因为它还添加了许多移植到浏览器的节点库,并且可以处理 CoffeeScript。

视频没有涵盖的一件事是如何制作一个具有多个视图的 Chrome 应用程序仍然以 DRY 方式使用 browserify。让我解释。通常,您的 browserify 命令采用一系列 JS 文件(设计为模块)并将其连接成带有一些包装糖的单个 JS 文件。您可以从内容页面、背景页面或弹出页面中引用该 JS 文件,这非常好。但是,如果您的应用程序同时具有背景页面弹出页面,您是否会在每个应用程序中包含相同的已编译 JS 文件?这不会导致 chrome 加载脚本两次(在两个实例中)吗?如果是这样,那么解释一切只是为了得到你想要的部分似乎是一种浪费。或者 require()/exports 模式是否可以防止对特定上下文可能不需要的模块进行不必要的解释?

如果这不是最佳实践,应该如何打包模块,使每个 页面 以干巴巴的方式获取所需的模块,而不必重复自己或每页有单独的 browserify 包?其他人是如何处理这个话题的?

【问题讨论】:

    标签: google-chrome-extension browserify


    【解决方案1】:

    我发现一种行之有效的技术是为每个上下文(例如背景、内容等)创建一个单独的包。这是一个示例目录结构:

    .
    ├── extension
    │   ├── js
    │   └── manifest.json
    ├── lib
    │   ├── background
    │   │   └── index.js
    │   ├── content
    │   │   └── index.js
    │   └── frame
    │       ├── index.js
    │       ├── models
    │       │   └── ...
    │       └── views
    │           └── ...
    └── package.json
    

    lib 目录中,为每个上下文创建一个文件夹,并以index.js 作为入口点。此文件将为该特定上下文引导应用程序,requireing 任何模块并初始化应用程序的该部分。

    然后使用browserifywatchify./extension/js/ 中创建捆绑包:

    $ browserify ./lib/background/index.js -o ./extension/js/background.js
    $ browserify ./lib/content/index.js -o ./extension/js/content.js
    $ browserify ./lib/frame/index.js -o ./extension/js/frame.js
    

    如果您打算在 background.jscontent.js 中重用相同的模块,只需在每个上下文中使用 require() 它,browserify 将相应地构建包。

    可以使用Gruntfile.jscustom npm script 简化此过程。

    您可以尝试这种方法的工作示例here

    【讨论】:

    • 完美。谢谢你。我认为这有助于我理解 chrome 扩展要求和 browserify 之间的关系。我的下一个 chrome 项目可能会采用这种格式。
    • 我也很好奇,你是怎么把线稿输入到上面的textarea的?这是外部编辑器的功能吗?
    • 我的经验是,这并不适用于所有情况。例如,browserify 在background.js 周围添加的语法糖使得无法正确访问来自chrome.extension.getBackgroundPage() 的变量。知道如何处理这个问题吗?
    【解决方案2】:

    在多个入口页面和一个单一的 JS 脚本的情况下,想法是封装你的 JS 逻辑,使你的 background.html 或后台脚本将所需的函数/对象暴露给全局(读取窗口)上下文.然后在其他入口页面(例如选项或弹出窗口)中,您可以使用它来访问后台页面的全局上下文:

    Application = chrome.extension.getBackgroundPage().myGlobalFunction();
    

    This SO Question 提供了一些关于布局和相互作用的见解。

    这允许您拥有一个版本的 browserify 创建的 JS,但允许它在相同扩展的其他页面上通信/执行。

    【讨论】:

      【解决方案3】:

      像 Browserify 这样的库通常旨在支持“单页 Web 应用程序”。也就是说,应用程序中通常只涉及一个 HTML 文件(通常是 public/index.html),它只是作为加载硬依赖项(例如 browserify 的串联输出)的入口点。其他一切都由 Javascript 以及您选择的任何前端框架(即 Backbone、SpineJS 等)管理。

      虽然单页 Web 应用程序可能包含多个“屏幕”数据,但这些页面的实际 HTML 通常是通过 AJAX 加载的 html 片段(通常使用 javascript 模板中间件,例如 Handlebars、Moustache、ECO 等) ,然后插入到页面的运行体中。也就是说 - 这些新的页面片段已经可以访问之前加载在此页面中的 javascript。

      因此,您对 SPA 感到厌烦,因为您只有一页,因此您不会重复使用 JS 导入。

      如果您以前习惯于全栈 Web 开发,其中大部分 UI 由服务器端语言呈现,那么单页 Web 应用程序的想法可能会有点令人震惊。虽然大多数 SPA 倾向于具有服务器端组件,但这通常简化为提供数据端点(AJAX 调用将命中)和持久性的 RESTful API。

      【讨论】:

      • 很好的解释。问题是关注 Google Chrome 扩展程序,这些扩展程序本质上具有不止一个入口点。 background.html、popup.html 和 options.html。使用 browserify,你有一个 JS 文件。我想我只是回答了我自己的问题......
      • 另外值得注意的是,在 Browserify 的最新(2.4+)版本中,您实际上可以使用 -r 标志生成多个生成的 JS 文件。如果你 require('foo') 并且 foo.js 没有内置到当前生成的源代码中,它将在页面的其他模块中查找它。换句话说,我可以有一个基础包,我可以在其中浏览化我所有的共享代码,并为特定于页面的模块提供单独的浏览器化包。结合您在下面的答案,可以为您提供一个很好的模块化扩展。不过,源地图完全是另一回事:/
      【解决方案4】:

      在 windows 10 下,我使用 MKLINK 跨项目共享我的源脚本(js)和样式(css)文件

      MKLINK /J "D:\Projects\Chrome Extension Projects\myproject\shared" "D:\Projects\Chrome Extension Projects\shared" 
      

      【讨论】:

      猜你喜欢
      • 2010-10-31
      • 1970-01-01
      • 2011-01-13
      • 2017-03-31
      • 2015-11-21
      • 2010-09-16
      • 1970-01-01
      • 1970-01-01
      • 2011-03-05
      相关资源
      最近更新 更多