从0到1打造Chrome Extension Cli

677 阅读2分钟

从0到1打造Chrome Extension Cli,用最主流的技术,提供最好的开发体验,支持Chrome Extension Manifest V3版本,让你的插件跑到时代的前沿:

  • 支持React 18、TypeScript、Arco Design、Tailwind CSS
  • 开箱即用,支持webpack5、swc编译
  • 支持Devtools debugger:Devtools debugger console是在控制台输出不了的
  • 内置工具函数:getCurrentTab、log等

架构

cli.drawio.png

目录总览

├── chrome-runtime
│   ├── background
│   │   └── background.ts
│   ├── content
│   │   ├── app
│   │   │   ├── index.tsx
│   │   │   └── src
│   │   │       ├── components
│   │   │       │   └── app
│   │   │       │       ├── app.tsx
│   │   │       │       └── index.ts
│   │   │       └── style
│   │   │           └── index.module.less
│   │   └── content.ts
│   └── devtools
│       └── devtools.ts
├── devtools-panel.html
├── devtools-src
│   ├── components
│   │   └── app
│   │       ├── app.tsx
│   │       └── index.ts
│   ├── index.tsx
│   └── style
│       └── index.less
├── devtools.html
├── option-src
│   ├── components
│   │   └── app
│   │       ├── app.tsx
│   │       └── index.ts
│   ├── index.tsx
│   └── style
│       └── index.less
├── options.html
├── package.json
├── popup-src
│   ├── components
│   │   └── app
│   │       ├── app.tsx
│   │       └── index.ts
│   ├── index.tsx
│   └── style
│       └── index.less
├── popup.html
├── public
│   └── manifest.json
├── sidebar-src
│   ├── components
│   │   └── app
│   │       ├── app.tsx
│   │       └── index.ts
│   ├── index.tsx
│   └── style
│       └── index.less
├── sidebar.html
├── tailwind.config.js
├── theme-src
│   ├── components
│   │   └── app
│   │       ├── app.tsx
│   │       └── index.ts
│   ├── index.tsx
│   └── style
│       └── index.less
├── theme.html
├── tsconfig.json
├── webpack.config.base.js
├── webpack.config.chrome.js
└── webpack.config.js

chorme-runtime

针对Chrome插件清单配置,这个目录下的文件是不能进行hash输出,只会跟原文件名称保持一致。主要分为三个部分:

  • content_script脚本:支持多脚本创建以及页面插入DOM UI定制
  • background脚本:支持页面通信等,是一个中间人的角色以及监听一些操作
  • devtools脚本:作为创建panel,slidbar的中间脚本,其余操作可以全部在panel、slidbar自己实现

页面布局

  • popup-src:对popup页面进行开发
  • option-src:对扩展程序配置页面进行开发
  • theme-src:对主题页面进行开发
  • panel-src:对devtools panel进行开发
  • slidbar-src:对devtools slidbar进行开发

核心实现

JS swc-loader编译

{
            // 不处理src以外js swc-loader 最佳实践
            test: /.(js|mjs|jsx|ts|tsx)$/,
            include: [
              path.join(__dirname, 'option-src'),
              path.join(__dirname, 'popup-src'),
              path.join(__dirname, 'theme-src'),
              path.join(__dirname, 'chrome-runtime'),
              path.join(__dirname, 'devtools-src'),
              path.join(__dirname, 'sidebar-src'),
            ],
            loader: require.resolve('swc-loader'),
            options: {
              module: {
                type: 'es6',
                ignoreDynamic: true,
              },
              jsc: {
                parser: {
                  syntax: 'typescript',
                  // tsx: false,
                  dynamicImport: true,
                },
                target: 'es2015',
                transform: {
                  react: {
                    runtime: 'automatic',
                    pragma: 'React.createElement',
                    pragmaFrag: 'React.Fragment',
                    throwIfNamespace: true,
                    development: false,
                    useBuiltins: true,
                  },
                },
              },
              sourceMaps: true,
            },
          },

CSS/CSS Module编译

 {
            test: /.module.less$/,
            use: [
              env === 'development' && require.resolve('style-loader'),
              env === 'production' && !isNoExtractCss
                ? {
                    loader: MiniCssExtractPlugin.loader,
                  }
                : require.resolve('style-loader'),
              {
                loader: require.resolve('css-loader'),
                options: {
                  importLoaders: 3,
                  sourceMap: true,
                  modules: {
                    mode: 'icss', // tailwind css local mode 有问题
                  },
                },
              },
              {
                loader: require.resolve('postcss-loader'),
                options: {
                  postcssOptions: {
                    ident: 'postcss',
                    config: false,
                    plugins: [
                      'tailwindcss',
                      'postcss-flexbugs-fixes',
                      [
                        'postcss-preset-env',
                        {
                          autoprefixer: {
                            flexbox: 'no-2009',
                          },
                          stage: 3,
                        },
                      ],
                    ],
                  },
                  sourceMap: true,
                },
              },
              {
                loader: require.resolve('resolve-url-loader'),
                options: {
                  sourceMap: true,
                  // root: [
                  //   path.join(__dirname, 'option-src'),
                  //   path.join(__dirname, 'popup-src'),
                  //   path.join(__dirname, 'theme-src'),
                  // ],
                },
              },
              {
                loader: require.resolve('less-loader'),
                options: {
                  sourceMap: true,
                },
              },
            ].filter(Boolean),
            sideEffects: true,
          },

CSS 抽离

需要配合上面css编译一起使用

plugins: [
    env === 'production' &&
      !isNoExtractCss &&
      new MiniCssExtractPlugin({
        filename: 'css/[name].[contenthash:8].css',
        chunkFilename: 'css/[name].[contenthash:8].chunk.css',
      })
    // TODO eslint plugin & TypeScript type check
  ].filter(Boolean),

Webpack 5 缓存

cache: {
    type: 'filesystem',
    version: '1234567890',
    cacheDirectory: path.join(__dirname, 'node_modules/.cache'),
    store: 'pack',
    buildDependencies: {
      defaultWebpack: ['webpack/lib/'],
      config: [__filename],
      tsconfig: [path.join(__dirname, 'tsconfig.json')],
    },
  },

多页面打包

// 入口文件配置
entry: {
    options: './option-src/index.tsx',
    popup: './popup-src/index.tsx',
    theme: './theme-src/index.tsx',
    'devtools-panel': './devtools-src/index.tsx',
    'sidebar': './sidebar-src/index.tsx',
},
// HtmlWebpackPlugin
...['options', 'popup', 'theme', 'devtools-panel', 'sidebar'].map(
      (v) =>
        new HtmlWebpackPlugin({
          inject: true,
          template: path.resolve(__dirname, `${v}.html`),
          filename: `${v}.html`,
          chunks: [v],
          ...(env === 'production'
            ? {
                minify: {
                   ...
                },
              }
            : undefined),
        }),
    ),

使用

暂时还没发包

git clone https://github.com/pandaCure/chrome-extension/tree/master/packages/template

开发

本地调式

调式option页面、theme页面、popup页面

pnpm run dev

访问option页面链接:http://localhost:8082/options.html

访问theme页面链接:http://localhost:8082/theme.html

访问popup页面链接:http://localhost:8082/popup.html

访问devtools-panel页面链接:http://localhost:8082/devtools-panel.html

访问sidebar页面链接:http://localhost:8082/sidebar.html

调式content页面

pnpm run dev:content

访问链接:http://localhost:8083/content.html

打包

pnpm run build

连载

上一篇:Chrome Extension 基础篇

下一篇:Chrome Extension 通讯篇