npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

webpack-chrome-extension

v1.0.0

Published

This is a Chrome browser extension developed by webpack and Vue, from the author slongzhang

Downloads

6

Readme

webpack-chrome-extension

初始化项目

npm init

安装[email protected]

npm install --save-dev [email protected]

创建开发目录

# windows cmd下执行
md src, src\background, src\contentScripts, src\options, src\popup, src\config, src\crxConfig\assets\images

# window powerShell下执行
mkdir -p src, src/background, src/contentScripts, src/options, src/popup, src/config, src/crxConfig/assets/images

# 其他平台自行创建

创建开发基础文件

# cmd
echo console.log('This is background.js')>src\background\index.js
echo console.log('This is contentScripts.js injected here')>>src\contentScripts\index.js
echo console.log('This is options.js')>src\options\main.js
echo console.log('This is popup.js')>src\popup\main.js
type nul>src\config\config.js

# powerShell
new-item src/background/index.js -type file -force -value "console.log('This is background.js')"
new-item src/contentScripts/index.js -type file -force -value "console.log('This is contentScripts.js injected here')"
new-item src/options/main.js -type file -force -value "console.log('This is options.js')"
new-item src/popup/main.js -type file -force -value "console.log('This is popup.js')"
new-item src/config/config.js

创建开发配置config/config.js

const config = {
    home: 'https://www.slong.ink',
    plugin: 'https://local.plugin.slong.ink',
    pluginApi: 'https://local.plugin.slong.ink/crx',
    prefix: '__ZSL__'
}
export default config

创建html页面模板

  • 根目录下新建index.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <meta name="author" content="[email protected]">
      <title>webpack-chrome-extension</title>
    </head>
    <body>
      <div id="app">
      </div>
    </body>
    </html>

配置webpack.config

创建webpack.config所需文件

  • 根目录下新建webpackConfig文件夹,并创建base.js 、build.js、dev.js、devOptions.js
# cmd
mkdir webpackConfig
type nul>webpackConfig\base.js
type nul>webpackConfig\build.js
type nul>webpackConfig\dev.js
type nul>webpackConfig\devOptions.js

# powerShell
mkdir webpackConfig
new-item webpackConfig/base.js
new-item webpackConfig/build.js
new-item webpackConfig/dev.js
new-item webpackConfig/devOptions.js

配置base.js

const path = require('path')
const webpack = require('webpack')
const rootPath = path.resolve(__dirname, '../'); // 定义项目根目录


const htmlWebpackPlugin = require('html-webpack-plugin') // 模板替换
const CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin') // 提取公共模块

const CopyWebpackPlugin = require("copy-webpack-plugin") // 文件拷贝插件

// 判断打包的版本
let manifestVersion = process.env.npm_config_MV;
if (manifestVersion && trim(manifestVersion) == 2) {
  manifestVersion = 2;
} else {
  manifestVersion = 3;
}

// 处理manifest文件(因为压缩的manifest.json不便查看和修改,json文件也无法注释, 因此改用js文件来转换)
// 获取fs句柄
const fs = require('fs')
// 获取manifest内容
const manifestData = require(`../src/crxConfig/manifest.v${manifestVersion}.js`)
const manifestFile = path.resolve(rootPath, `src/crxConfig/manifest.min.json`)
// 写入数据
fs.writeFileSync(manifestFile, JSON.stringify(manifestData));


module.exports = {
  entry: {
    background: path.resolve(rootPath, 'src/background/index.js'),
    contentScripts: path.resolve(rootPath, 'src/contentScripts/index.js'),
    options: path.resolve(rootPath, 'src/options/main.js'),
    popup: path.resolve(rootPath, 'src/popup/main.js'),
  },
  output: {
    path: path.resolve(rootPath, 'dist'),
    filename: '[name]/index.js'
  },
  module: {
    rules: [{
        test: /\.css$/,
        use: [{
            loader: 'style-loader'
          },
          {
            loader: 'css-loader',
            options: {
              modules: true
            }
          }
        ]
      },
      {
        test: /\.(png|jpg|gif|svg|jpeg)$/,
        use: [{
          loader: 'url-loader',
          options: {
            limit: 8192,
            // fallback: { // 回调函数,file-loader 可以写在回调里,也可忽略,webpack会自动查找处理
            //   loader: 'file-loader',
            //   options: {
            //     publicPath: './dist/'
            //   }
            // }
          }
        }]
      },
      {
        test: /\.js$/,
        exclude: /(node_modules|bower_components)/, // 过滤目录
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['es2015']
          }
        }
      },
      {
        test: /\.vue$/,
        use: ['vue-loader']
      }
    ]
  },
  resolve: {
    extensions: ['.js', '.css', '.vue'], // 省略的后缀
    alias: {
      "@src": rootPath + '/src',
      "@options": path.resolve(rootPath, '/src/options'),
      "@popup": path.resolve(rootPath, '/src/popup'),
      "vue$": "vue/dist/vue.esm.js"
    }
  },
  plugins: [
    // 提取公共部分
    new CommonsChunkPlugin({
      // 从 指定的现成的 Chunk 中提取公共的部分
      chunks: ['options', 'popup'], // 从options和popup文件抽取
      // 把公共的部分放到 base 中
      name: 'common'
    }),
    // 导出options
    new htmlWebpackPlugin({
      template: 'index.html',
      filename: 'options/index.html',
      // title: '',
      //增加指定的chunks
      chunks: ['common', 'options']
    }),
    // 导出popup
    new htmlWebpackPlugin({
      template: 'index.html',
      filename: 'popup/index.html',
      // title: '',
      //增加指定的chunks
      chunks: ['common', 'popup']
    }),
    // banner声明条
    new webpack.BannerPlugin(`
    author: 'slongZhang',
    email: '[email protected]',
    date: ${new Date().toDateString()}`),
    // 拷贝文件
    new CopyWebpackPlugin([{
        from: path.resolve(rootPath, "src/crxConfig/assets"),
        to: path.resolve(rootPath, "dist/assets")
      },
      {
        from: manifestFile,
        to: path.resolve(rootPath, "dist/manifest.json")
      },
    ])
  ]
}

配置build.js

const baseConfig = require('./base.js');
const path = require('path')
const webpack = require('webpack');
const webpackMerge = require('webpack-merge');
const uglifyjsWebpackPlugin = require('uglifyjs-webpack-plugin');
const {
  CleanWebpackPlugin
} = require('clean-webpack-plugin') // 清除上次打包的dist
const ZipPlugin = require("zip-webpack-plugin") // 打包压缩插件

module.exports = webpackMerge({
    plugins: [
      // 清除旧的dish
      new CleanWebpackPlugin(),
      // 丑化压缩代码
      new uglifyjsWebpackPlugin()
    ]
  },
  baseConfig, {
    plugins: [
      // 压缩打包
      new ZipPlugin({
        path: path.resolve(__dirname, "../dist"),
        filename: 'dist.zip'
      })
    ]
  })

配置dev.js

const baseConfig = require('./base.js');
module.exports = baseConfig

配置devOptions.js

const baseConfig = require('./base.js');
const path = require('path')
const webpackMerge = require('webpack-merge');

module.exports = webpackMerge(baseConfig, {
  devServer: {
    contentBase: path.resolve(__dirname, "../dist/options/"),
    inline: true
  }
});

安装webpack依赖

# css样式文件处理依赖
npm install --save-dev [email protected] [email protected]

# 图片和文件处理依赖
npm install --save-dev [email protected] [email protected]

# babel-loader 处理浏览器兼容问题,可以将es6转成es5
npm install --save-dev [email protected] [email protected] [email protected]

# 安装vue解析器(这边按vue2来配置的,如使用vue3或其他框架的请自行修改,如未使用框架的需自行移除配置文件里与vue相关的代码)
npm install --save-dev [email protected] [email protected]
npm install --save [email protected]
# 注意vue-template-compiler的版本号要和vue的版本号一致才能解析


# 打包前清除dist插件(webpack插件)
npm install --save-dev [email protected]

# 拷贝插件
npm install --save-dev [email protected]

# 模板插件
npm install --save-dev [email protected]

# 代码压缩插件
npm install --save-dev [email protected]

# 安装webpack-merge
npm install --save-dev [email protected]

# 安装打包脚本
npm install --save-dev [email protected]

# 本地服务端
npm install --save-dev [email protected]

创建manifest.json(浏览器开发配置表)

# cmd
type nul>src\crxConfig\manifest.v2.js
type nul>src\crxConfig\manifest.v3.js

# powerShell
new-item src/crxConfig/manifest.v2.js
new-item src/crxConfig/manifest.v3.js
  • manifest.v2.json是chrome浏览器扩展v2版本开发规范,v3则是chrome最新开发规范,新开发的建议直接上手v3

    image-20220514145632730

  • manifest规范不详细解释介绍,不懂的自己看chrome文档

配置manifest.v2.js

module.exports = {
  // 开发规范版本
  "manifest_version": 2,
  //  插件名
  "name": "webpack dev chrome extension MV2",
  // 插件版本
  "version": "1.0.0",
  // 插件描述
  "description": "a chrome extension with [email protected]",
  // 选项页
  "options_page": "options/index.html",
  // 浏览器右上角图标设置, browser_action、page_action、app必选三选一
  "browser_action": {
    // // 扩展显示的图标(位于浏览器右上角)
    // "default_icon": "assets/images/icon48.png",
    // 鼠标悬停在图标时显示的标题
    "default_title": "webpack dev chrome extension MV2",
    // 页面
    "default_popup": "popup/index.html"
  },
  // // 图标
  // "icons": {
  //   "16": "assets/images/icon16.png",
  //   "48": "assets/images/icon48.png",
  //   "128": "assets/images/icon128.png"
  // },
  // 常驻后台js或后台页面
  "background": {
    // 2种指定方式,如果指定js,那么会自动生成一个背景页
    // "page": "background.html"
    "scripts": ["background/index.js"]
  },
  // 权限申请
  "permissions": [
    "tabs",
    // 插件本地存储
    "storage",
    // 获取cookie权限
    "cookies",
    // 定时器
    "alarms",
    // 脚本注入功能
    "scripting"
    // 请求头拦截与修改
    , 'webRequest', 'webRequestBlocking',
    // 声明所有域名都有访问权限
    "*://*/*"
  ],
  // 允许web与bg通信的域名
  "externally_connectable": {
    "matches": [
      "*://*.slong.ink/*",
      // 百度(平时调试使用)
      "*://*.baidu.com/*"
    ]
  },
  // 注入到页面的脚本
  "content_scripts": [{
    "matches": [
      // "*://*.baidu.com/*", // 匹配百度
      // "http://*/*", // 匹配所有http开头的
      // "https://*/*", // 匹配所有https开头的
      "<all_urls>" // 匹配所有
    ],
    "js": ["contentScripts/index.js"],
    "css": [],
    "run_at": "document_start" // 什么时候执行注入,"document_start"页面打开注入
  }],
  // 定义可以被外部访问的文件资源(当前插件的文件资源如图片,脚本,样式等)
  "web_accessible_resources": [

  ],
  // 插件主页
  "homepage_url": "https://www.slong.ink",
  // 更新地址
  "update_url": "https://clients2.google.com/service/update2/crx"
}

配置manifest.v3.js

module.exports = {
  // 插件开发规范版本
  "manifest_version": 3,
  // 插件名
  "name": "webpack dev chrome extension MV3",
  // 插件版本号
  "version": "1.0.1",
  // 插件描述
  "description": "a chrome extension with [email protected]",
  // 选项页
  "options_page": "options/index.html",
  // 浏览器右上角图标设置,V3:action(V2:browser_action、page_action、app必选三选一)
  "action": {
    // // 扩展显示的图标(位于浏览器右上角)
    // "default_icon": "assets/images/icon48.png",
    // 鼠标悬停在图标时显示的标题
    "default_title": "webpack dev chrome extension MV3",
    // 点击后的页面
    "default_popup": "popup/index.html"
  },
  // // 图标
  // "icons": {
  //   "16": "assets/images/icon16.png",
  //   "48": "assets/images/icon48.png",
  //   "128": "assets/images/icon128.png"
  // },
  // 常驻后台js或后台页面
  "background": {
    "service_worker": "background/index.js"
  },
  // 权限申请
  "permissions": [
    "tabs",
    // 插件本地存储
    "storage",
    // 获取cookie权限
    "cookies",
    // 定时器
    "alarms",
    // 脚本注入功能
    "scripting"
    // 请求头拦截与修改
    , 'webRequest', 'webRequestBlocking'
  ],
  // 主机域名权限(可以通过executeScript或者insertCSS访问的网站)
  "host_permissions": [
    "*://*/*"
  ],
  // 允许web与bg通信的域名(注意这里不支持泛域名)
  "externally_connectable": {
    "matches": [
      "*://*.slong.ink/*",
      // 百度(平时调试使用)
      "*://*.baidu.com/*"
    ]
  },
  // 注入到页面的脚本
  "content_scripts": [{
    "matches": [
      // "*://*.baidu.com/*", // 匹配百度
      // "http://*/*", // 匹配所有http开头的
      // "https://*/*", // 匹配所有https开头的
      "<all_urls>" // 匹配所有
    ],
    "js": ["contentScripts/index.js"],
    "css": [],
    "run_at": "document_start" // 什么时候执行注入,"document_start"页面打开注入
  }],
  // 定义可以被外部访问的文件资源(当前插件的文件资源如图片,脚本,样式等)
  "web_accessible_resources": [

  ],
  // 插件主页
  "homepage_url": "https://www.slong.ink",
  // 更新地址
  "update_url": "https://clients2.google.com/service/update2/crx"
}

配置package.js脚本命令

"scripts": {
    "dev": "webpack --config webpackConfig/dev.js",
    "devOptions": "webpack-dev-server --config webpackConfig/devOptions.js --open",
    "build": "webpack --config webpackConfig/build.js"
  }

image-20220514233218690

popup和options添加vue框架

配置popup

  • src/popup目录下新建App.vue

    <template lang="html">
      <div class="wrap">
        <h1>{{message}}</h1>
      </div>
    </template>
    
    <script>
    export default {
      name: 'App',
      data() {
        return {
          message: 'hello popup!'
        }
      }
    }
    </script>
    
    <style lang="css" scoped>
    .wrap {
      width: 200px;
    }
    h1{
      color: red;
    }
    </style>
  • 编辑src/popup/main.js

    import config from '@src/config/config'
    import Vue from 'vue'
    import App from './App.vue'
    
    new Vue({
      el: '#app',
      render: h => h(App)
    })

配置options

  • src/optins下新建App.vue

    <template lang="html">
      <div>
        <router-link to="/Home">首页</router-link>
        <router-link to="/About">关于</router-link>
        <router-view></router-view>
      </div>
    </template>
    
    <script>
    
    export default {
      name: 'App',
      data() {
        return {
          message: 'hello options'
        }
      },
      components: {
      }
    }
    </script>
    
    <style lang="css" scoped>
    </style>
  • 编辑src/options/main.js

    import config from '@src/config/config'
    import Vue from 'vue'
    import App from './App.vue'
    import router from './router'
    
    new Vue({
      el: '#app',
      router,
      render: h => h(App)
    })
  • 安装vuex 和 vue-router

    npm install --save [email protected] [email protected]
  • 新建vue项目文件和目录

    # cmd
    md src\options\common, src\options\components, src\options\router, src\options\store, src\options\views
    
    # window powerShell下执行
    mkdir -p src/options/common, src/options/components, src/options/router, src/options/store, src/options/views
  • 创建两个案例页面

    • 创建src/options/views/Home.vue

      <template lang="html">
        <div>
          <h2>我是home页面</h2>
          <p>home home home</p>
        </div>
      </template>
      
      <script>
      export default {
        name: 'Home'
      }
      </script>
      
      <style lang="css" scoped>
      </style>
    • 创建src/options/views/About.vue

      <template lang="html">
          <div>
            <h2>我是about页面</h2>
            <p>about about about</p>
          </div>
        </template>
      
        <script>
        export default {
          name: 'About'
        }
        </script>
      
        <style lang="css" scoped>
        </style>
  • 创建路由文件src\options\router\index.js

    // 配置路由相关信息
    import VueRouter from 'vue-router'
    import Vue from 'vue'
    
    // 1.通过Vue.use(插件),安装插件
    Vue.use(VueRouter)
    
    // 导入组件
    import Home from '../views/Home'
    import About from '../views/About'
    
    // 2.创建VueRouter对象
    const routes = [{
        path: '',
        redirect: '/home'
      },
      {
        path: '/home',
        component: Home
      }, {
        path: '/about',
        component: About
      }
    ]
    const router = new VueRouter({
      routes,
      mode: 'history'
    })
    
    export default router

运行 or 打包

# 打包开发版
npm run dev

# 运行热加载options
npm run devOptions

# 打包发行版
npm run build

注意: (默认打包mv3规范,如需打包v2则命令后面添加 --MV=2,如 npm run dev --MV=2)

最后总结

  • MV3 不再提供document和window接口了,background后台页如需解析html dom对象可安装cheerio解决

  • 插件开发过程中,可能会用的的类库推荐(根据自身情况选择安装)

    # 支持dom解析(可解决background不支持dom的问题)
    npm install --save [email protected]
    
    # 支持数据压缩和解压
    npm install --save [email protected]