文章目录
紧接上一篇文章对chrome插件的基本介绍,这里我们就来开始真正实践一下插件的开发吧,第一部分就从开发环境搭建入手吧,这一部分也是插件开发和Web-SPA应用开发区别较大的一部分
预期目标
预期目标是搭建React+TS+Antd的插件开发环境,支持build生成插件所需要的所有文件
最终理想的build目录应该接近下述形态:
├─ favicon.ico <--这个没有也行,用不到
├─ index.html <--popup入口页面
├─ insert.js <--插入到目标页面执行的js(非必须,视业务需求而定,后面笔记会说到)
├─ manifest.json <--插件的配置文件
├─ /static
| ├─ /css
| | ├─ content.css <--content页面样式(会与目标页面互相污染)
| | └─ main.css <--popup页面样式(不会与目标页面互相污染)
| ├─ /js
| | ├─ background.js <--background script
| | ├─ content.js <--content script
| | └─ main.js <--popup script
| └─ /media <--项目的图片资源存放目录
上述包含了插件所需要的popup,content和background组成部分
开发环境搭建实践
create-react-app搭建标准react工程
这里我采用react开发都很熟悉的脚手架create-react-app来进行,如果希望使用TS的小伙伴记得添加TS模板的参数哈
快速新建标准react+ts工程:
npx create-react-app my-app --template typescript
cd my-app
npm start
之后大家可以直接执行npm run ejcet来暴露webpack的配置,后续需对webpack进行修改
工程开发目录配置
这里我参考了这篇博客进行了开发目录的配置,大家按照自己的风格修改:https://zhuanlan.zhihu.com/p/137793202
├─ /config <--配置目录(由eject生成)
├─ /public <--popup入口页面
| ├─ /images <--图片目录
| | ├─ icon.png <--插件图标
| ├─ favicon.ico <--这个没有也行,用不到
| ├─ index.html <--popup入口页面
| ├─ insert.js <--插入到目标页面执行的js(非必须,视业务需求而定)
| ├─ manifest.json <--插件的配置文件
├─ /scripts <--项目构建运行脚本(由eject生成)
├─ /src <--开发目录
| ├─ /api <--API公用目录
| | ├─ index.js
| ├─ /background <--background script开发目录
| | ├─ index.js
| ├─ /common <--公用资源目录
| | ├─ /js <--公用js目录
| | └─ /stylus <--公用样式目录(本demo使用stylus)
| ├─ /content <--content script开发目录
| | ├─ /components <--content 组件目录
| | ├─ /images <--content 图片目录
| | ├─ content.styl <--content 样式
| | └─ index.js <--content script主文件
| ├─ /popup <--popup开发目录
| | ├─ /pages <--popup 页面目录
| | ├─ /components <--popup 组件目录
| | ├─ index.js <--popup 主文件
| ├─ index.js <--项目主文件,也是popup入口文件
├─ pakeage.json
修改webpack生成上述build目录
重点来了,插件开发并不像SPA应用一样一个入口就足够了,需要修改webpack的配置让其可以打包符合上述build目录要求的产物
设置多入口
为了让popup,background,content都拿打包对应的js文件文件,需要设置多入口,主要是修改entry字段
我们来对config/webpack.config.js作如下修改:
...
entry: {
main: [
isEnvDevelopment &&
require.resolve('react-dev-utils/webpackHotDevClient'),
paths.appIndexJs,
].filter(Boolean),
content: './src/content/index.js',
background: './src/background/index.ts'
}
核心代码位置大约在173-198行
将原来的entry换成了对象,每个对象的key对应一个入口
固定build生成的文件名
因为manifest.json中配置引用的js文件名是固定的,所以我们需要保证每次打包的文件名不变(默认会加上hash值),主要的工作如下:
- 去掉文件hash值,删除[contenthash:8],共4处。(当然你也可以写一些工具尝试在打包阶段动态修改manifest.json文件,这样这个步骤就不需要了)
- 由于是多入口,需要将static/js/bundle.js修改为static/js/[name].bundle.js。
- 将runtimeChunk设置为false,否则build后还会多生成runtime-background.js、runtime-content.js、runtime-main.js。
- 注释掉splitChunks,取消分包,否则会生成类似1.chunk.js、2.chunk.js等文件。
继续修改上述webpack.config.js:
// 大约206行
filename: isEnvProduction
? 'static/js/[name].js'
: isEnvDevelopment && 'static/js/[name].bundle.js',
// 大约214行
chunkFilename: isEnvProduction
? 'static/js/[name].chunk.js'
: isEnvDevelopment && 'static/js/[name].chunk.js',
// 大约302行
/ chrome插件开发,取消分包机制
// splitChunks: {
// chunks: 'all',
// name: isEnvDevelopment,
// },
...
runtimeChunk: false
// 大约642行
new MiniCssExtractPlugin({
filename: 'static/css/[name].css',
chunkFilename: 'static/css/[name].chunk.css',
}),
设置popup不引入另外两个模块的js
设置index.html只引入main.js,否则popup页面会把background/index.js和content/index.js也引入
// 566行
new HtmlWebpackPlugin(
Object.assign(
{},
{
inject: true,
// html只引入popup代码,chrome插件开发不能引入content和background的代码
chunks: ['main'],
template: paths.appHtml,
},
isEnvProduction
? {
minify: {
removeComments: true,
collapseWhitespace: true,
removeRedundantAttributes: true,
useShortDoctype: true,
removeEmptyAttributes: true,
removeStyleLinkTypeAttributes: true,
keepClosingSlash: true,
minifyJS: true,
minifyCSS: true,
minifyURLs: true,
},
}
: undefined
)
),
以上基本完成了webpack的改造工作了
引入Antd
这是一款react使用比较广泛的UI组件库,有需要的同学可以看下
其实这里antd的引入方式和传统开发一样,这里还是贴一下代码,首先安装一下antd的库:
npm install antd --save
接着我们还需要补充antd的按需加载能力,这一部分官网也有介绍,首先安装babel-plugin-import:
npm install babel-plugin-import --save-dev
接着修改package.json:
"babel": {
"presets": [
"react-app"
],
+ "plugins": [
+ [
+ "import",
+ {
+ "libraryName": "antd",
+ "style": "css"
+ }
+ ]
+ ]
}
回顾总结
- react+ts+antd的chrome插件开发环境搭建能力
- webpack多入口的配置实践
- webpack产物名称和路径的配置