基于 webpack 的 chrome 扩展开发探索

最近利用闲暇时间在进行一款 chrome 扩展 V2EX-HELPER 的开发(如果巧遇 V 友欢迎试用),今天把它彻底改成了用 webpack 打包依赖的模式,不由得感概 webpack 的强大,记录一二。

之前的项目开发是非常传统的 chrome 扩展开发方式,代码可以猛戳 这里。截止目前,该扩展主要由三部分组成,background-scripts,content-scripts 以及 option 页面。一开始做这个扩展的时候,只是为了实现一个功能,所以就一个 background.js 文件,一个 content.js 文件,甚至都不需要 option 页面,但是随着集成的功能越来越多,js 的依赖也越来越复杂。

比如有一个查看对话详情的功能,manifest.json 文件中的 content_scripts 项是这样配置的:

 {
  // 对话详情
  "matches": ["*://www.v2ex.com/t/*"],
  "js": [
    "content-scripts/lib/jquery.min.js",
    "content-scripts/lib/jquery.modal.min.js",
    "content-scripts/checkConversation/checkConversation.js"
  ],
  "css": [
    "styles/all.css",
    "styles/lib/css-loader.css",
    "styles/lib/jquery.modal.min.css"
  ],
  "run_at": "document_end"
}

也就是说,这个功能的实现,页面中插入了三个 js 文件和三个 css 文件。

我们来看下当时主要文件结构:

├── background-scripts
│   ├── background.js
│   ├── getCfg.js
│   ├── lib
│   └── notifications.js
├── content-scripts
│   ├── checkConversation
│   ├── checkReply
│   ├── lib
│   ├── signin
│   ├── uploadImg
│   └── zoom
├── manifest.json
├── option
│   ├── option.html
│   └── option.js
└── styles
    ├── all.css
    └── lib

在 content-scripts 目录下,我为每个功能新增了一个文件夹,然后相应的 js 文件放里面,因为可能会有文件的复用(比如多次复用 jquery),我把这类文件放到一个叫 lib 的目录下。其实理想的想法是,跟组件化思路类似,将一个功能的文件放到一个文件夹下,但是这样的话,可能 checkConversation 文件夹下会有个 jquery 文件,checkReply 文件夹下也有个 jquery 文件,有代码洁癖的人完全不能忍。而且,content_scripts 其实还配置了 css,我将它放在了独立的 styles 文件夹下,文件如此分散实际上相当难以维护。

理想的目录结构可能会是这样:

├── content-scripts
│   ├── checkConversation
│   │   └── checkConversation.js
│   │   └── jquery.min.js
│   │   └── A.css
│   ├── checkReply
│   │   ├── insertCheckBtn.js
│   │   └── jump.js
│   │   └── B.css

之后,background-scripts 中的文件也越来越多,因为逻辑放在一个文件实在是难以维护。

决定采用 webpack 做打包工具后,问题迎刃而解。

来看目前的主要文件结构:

├── LICENSE ├── README.md ├── app │   ├── background-scripts │   │   ├── background.js │   │   ├── checkConversation.js │   │   ├── setNotifications.js │   │   └── uploadImg.js │   ├── content-scripts │   │   ├── checkConversation │   │   │   ├── checkConversation.js │   │   │   └── sass │   │   ├── checkReply │   │   │   ├── insertCheckBtn.js │   │   │   └── jump.js │   │   ├── signin │   │   │   └── signin.js │   │   ├── uploadImg │   │   │   ├── sass │   │   │   └── uploadImg.js │   │   └── zoom │   │   └── zoom.js │   ├── option │   │   ├── option.html │   │   └── option.js │   ├── popup │   │   ├── popup.html │   │   └── popup.js │   └── settings │   └── settings.js ├── extension │   ├── background-scripts │   │   └── background.js │   ├── content-scripts │   │   ├── checkConversation │   │   │   └── checkConversation.js │   │   ├── checkReply │   │   │   ├── insertCheckBtn.js │   │   │   └── jump.js │   │   ├── signin │   │   │   └── signin.js │   │   ├── uploadImg │   │   │   └── uploadImg.js │   │   └── zoom │   │   └── zoom.js │   ├── docs │   │   └── img │   ├── icons │   │   ├── icon_16.png │   │   ├── icon_19.png │   │   ├── icon_38.png │   │   └── icon_48.png │   ├── manifest.json │   ├── option │   │   ├── option.html │   │   └── option.js │   └── popup │   ├── popup.html │   └── popup.js ├── package.json └── webpack.config.js

extension 文件夹內为最终的扩展打包文件,而 app 文件夹为原始开发文件,可以看到,一个独立的功能最终都被打包成了一个 js 文件,用了 npm 当作包管理工具,也不用怕文件多次复制的问题。而 webpack 一切皆为模块的思想,配合 ES6 的模块,成功将多个 js 以及 css 依赖,打包入一个文件,同时也简化了 manifest.json 文件中的 content_scripts
配置,不得不说这正是我期望的效果。

webpack 的配置(webpack.config.js),多入口不用多说,jquery + jquery 插件的使用遇到了一点问题,记录如下。

plugins 选项配置如下:

plugins: [
  new webpack.ProvidePlugin({
    $: 'jquery',
    jQuery: 'jquery',
    'window.jQuery': 'jquery',
    'window.$': 'jquery'
  })
]

module 中增加一条 rules(先 npm i expose-loader):

{
  test: require.resolve('jquery'),
  use: [{
    loader: 'expose-loader',
    options: 'jQuery'
  },{
    loader: 'expose-loader',
    options: '$'
  }]
}

然后就可以全局使用 jQuery 了(无需另写代码引入),也可以在文件中使用 jquery 插件了。

比如在查看对话功能中,使用了 jquery 以及 jquery.modal 这个 jquery 插件,js 文件中这样写(当然首先 npm i jquery-modal):

import 'jquery-modal/jquery.modal.min.css'
import 'jquery-modal/jquery.modal.min.js'

随着对于 webpack 的了解逐渐加深,真心觉得真的是开发利器(当然 npm 也是不逞多让,两者配合开发真是爽歪歪)。

其实现实工作开发中,webpack 甚至 react、vue 等框架我都还没用过,非常遗憾,有实际的开发需求肯定才有更大动力去探索和填坑,希望自己早日能接触到基于这类的开发吧。

上一篇:搭建eclipse环境下 Nutch+Mysql 二次开发环境


下一篇:SQL小细节