React开发chrome插件系列教程之插件开发环境搭建

1,686 阅读4分钟

这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战

紧接上一篇文章对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进行修改

工程开发目录配置

这里我参考了这篇博客进行了开发目录的配置,大家按照自己的风格修改: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产物名称和路径的配置