从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等
架构
目录总览
├── 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