起
最近利用闲暇时间在进行一款 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 做打包工具后,问题迎刃而解。
来看目前的主要文件结构:
├── 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
│ ├── manifest.json
│ ├── option
│ │ ├── option.html
│ │ └── option.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 了(无需另写代码引入,当然首先需要 npm i 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 等框架我都还没用过,非常遗憾,有实际的开发需求肯定才有更大动力去探索和填坑,希望自己早日能接触到基于这类的开发吧。