generated from Goyslop/web-extension-starter
Initial commit
This commit is contained in:
commit
05aac07a6c
38
.babelrc
Normal file
38
.babelrc
Normal file
@ -0,0 +1,38 @@
|
||||
{
|
||||
"presets": [
|
||||
[
|
||||
// Latest stable ECMAScript features
|
||||
"@babel/preset-env",
|
||||
{
|
||||
"useBuiltIns": false,
|
||||
// Do not transform modules to CJS
|
||||
"modules": false,
|
||||
"targets": {
|
||||
"chrome": "49",
|
||||
"firefox": "52",
|
||||
"opera": "36",
|
||||
"edge": "79"
|
||||
}
|
||||
}
|
||||
],
|
||||
"@babel/typescript",
|
||||
"@babel/react"
|
||||
],
|
||||
"plugins": [
|
||||
["@babel/plugin-proposal-class-properties"],
|
||||
["@babel/plugin-transform-destructuring", {
|
||||
"useBuiltIns": true
|
||||
}],
|
||||
["@babel/plugin-proposal-object-rest-spread", {
|
||||
"useBuiltIns": true
|
||||
}],
|
||||
[
|
||||
// Polyfills the runtime needed for async/await and generators
|
||||
"@babel/plugin-transform-runtime",
|
||||
{
|
||||
"helpers": false,
|
||||
"regenerator": true
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
5
.eslintignore
Normal file
5
.eslintignore
Normal file
@ -0,0 +1,5 @@
|
||||
node_modules/
|
||||
dist/
|
||||
extension/
|
||||
.yarn/
|
||||
.pnp.js
|
||||
34
.eslintrc.json
Normal file
34
.eslintrc.json
Normal file
@ -0,0 +1,34 @@
|
||||
{
|
||||
"extends": [
|
||||
"@abhijithvijayan/eslint-config/typescript",
|
||||
"@abhijithvijayan/eslint-config/node",
|
||||
"@abhijithvijayan/eslint-config/react"
|
||||
],
|
||||
"parserOptions": {
|
||||
"project": [
|
||||
"./tsconfig.json"
|
||||
],
|
||||
"sourceType": "module"
|
||||
},
|
||||
"rules": {
|
||||
"no-console": "off",
|
||||
"no-extend-native": "off",
|
||||
"react/jsx-props-no-spreading": "off",
|
||||
"jsx-a11y/label-has-associated-control": "off",
|
||||
"class-methods-use-this": "off",
|
||||
"max-classes-per-file": "off",
|
||||
"node/no-missing-import": "off",
|
||||
"node/no-unpublished-import": "off",
|
||||
"node/no-unsupported-features/es-syntax": ["error", {
|
||||
"ignores": ["modules"]
|
||||
}]
|
||||
},
|
||||
"env": {
|
||||
"webextensions": true
|
||||
},
|
||||
"settings": {
|
||||
"node": {
|
||||
"tryExtensions": [".tsx"] // append tsx to the list as well
|
||||
}
|
||||
}
|
||||
}
|
||||
12
.github/FUNDING.yml
vendored
Normal file
12
.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: [abhijithvijayan]
|
||||
patreon: abhijithvijayan
|
||||
open_collective: abhijithvijayan
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: abhijithvijayan
|
||||
otechie: # Replace with a single Otechie username
|
||||
custom: ['https://www.buymeacoffee.com/abhijithvijayan', 'https://www.paypal.me/iamabhijithvijayan']
|
||||
204
.gitignore
vendored
Normal file
204
.gitignore
vendored
Normal file
@ -0,0 +1,204 @@
|
||||
# ignore haters
|
||||
haters/
|
||||
|
||||
### WebStorm+all ###
|
||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
||||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||
|
||||
# User-specific stuff
|
||||
.idea/**/workspace.xml
|
||||
.idea/**/tasks.xml
|
||||
.idea/**/usage.statistics.xml
|
||||
.idea/**/dictionaries
|
||||
.idea/**/shelf
|
||||
|
||||
# Generated files
|
||||
.idea/**/contentModel.xml
|
||||
|
||||
# Sensitive or high-churn files
|
||||
.idea/**/dataSources/
|
||||
.idea/**/dataSources.ids
|
||||
.idea/**/dataSources.local.xml
|
||||
.idea/**/sqlDataSources.xml
|
||||
.idea/**/dynamic.xml
|
||||
.idea/**/uiDesigner.xml
|
||||
.idea/**/dbnavigator.xml
|
||||
|
||||
# Gradle
|
||||
.idea/**/gradle.xml
|
||||
.idea/**/libraries
|
||||
|
||||
# Gradle and Maven with auto-import
|
||||
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||
# since they will be recreated, and may cause churn. Uncomment if using
|
||||
# auto-import.
|
||||
# .idea/artifacts
|
||||
# .idea/compiler.xml
|
||||
# .idea/jarRepositories.xml
|
||||
# .idea/modules.xml
|
||||
# .idea/*.iml
|
||||
# .idea/modules
|
||||
# *.iml
|
||||
# *.ipr
|
||||
|
||||
# CMake
|
||||
cmake-build-*/
|
||||
|
||||
# Mongo Explorer plugin
|
||||
.idea/**/mongoSettings.xml
|
||||
|
||||
# File-based project format
|
||||
*.iws
|
||||
|
||||
# IntelliJ
|
||||
out/
|
||||
|
||||
# mpeltonen/sbt-idea plugin
|
||||
.idea_modules/
|
||||
|
||||
# JIRA plugin
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
# Cursive Clojure plugin
|
||||
.idea/replstate.xml
|
||||
|
||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||
com_crashlytics_export_strings.xml
|
||||
crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
fabric.properties
|
||||
|
||||
# Editor-based Rest Client
|
||||
.idea/httpRequests
|
||||
|
||||
# Android studio 3.1+ serialized cache file
|
||||
.idea/caches/build_file_checksums.ser
|
||||
|
||||
### WebStorm+all Patch ###
|
||||
# Ignores the whole .idea folder and all .iml files
|
||||
# See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360
|
||||
|
||||
.idea/
|
||||
|
||||
# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023
|
||||
|
||||
*.iml
|
||||
modules.xml
|
||||
.idea/misc.xml
|
||||
*.ipr
|
||||
|
||||
# Sonarlint plugin
|
||||
.idea/sonarlint
|
||||
|
||||
# End of https://www.toptal.com/developers/gitignore/api/webstorm+all
|
||||
|
||||
### Node ###
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# TypeScript v1 declaration files
|
||||
typings/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
.env.test
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
|
||||
# next.js build output
|
||||
.next
|
||||
|
||||
# nuxt.js build output
|
||||
.nuxt
|
||||
|
||||
# react / gatsby
|
||||
public/
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
### Sass ###
|
||||
.sass-cache/
|
||||
*.css.map
|
||||
*.sass.map
|
||||
*.scss.map
|
||||
|
||||
## Build directory
|
||||
extension/
|
||||
dist/
|
||||
.awcache
|
||||
|
||||
# yarn 2
|
||||
# https://github.com/yarnpkg/berry/issues/454#issuecomment-530312089
|
||||
.yarn/*
|
||||
!.yarn/releases
|
||||
!.yarn/plugins
|
||||
.pnp.*
|
||||
19
.travis.yml
Normal file
19
.travis.yml
Normal file
@ -0,0 +1,19 @@
|
||||
language: node_js
|
||||
cache:
|
||||
directories:
|
||||
- ~/.npm
|
||||
node_js:
|
||||
- 12
|
||||
git:
|
||||
depth: 3
|
||||
script:
|
||||
- yarn run build
|
||||
deploy:
|
||||
provider: pages
|
||||
skip-cleanup: true
|
||||
keep-history: true
|
||||
github-token: $GITHUB_TOKEN
|
||||
local-dir: extension
|
||||
target-branch: extension
|
||||
on:
|
||||
branch: master
|
||||
76
CODE_OF_CONDUCT.md
Normal file
76
CODE_OF_CONDUCT.md
Normal file
@ -0,0 +1,76 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as
|
||||
contributors and maintainers pledge to making participation in our project and
|
||||
our community a harassment-free experience for everyone, regardless of age, body
|
||||
size, disability, ethnicity, sex characteristics, gender identity and expression,
|
||||
level of experience, education, socio-economic status, nationality, personal
|
||||
appearance, race, religion, or sexual identity and orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment
|
||||
include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or
|
||||
advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic
|
||||
address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable
|
||||
behavior and are expected to take appropriate and fair corrective action in
|
||||
response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or
|
||||
reject comments, commits, code, wiki edits, issues, and other contributions
|
||||
that are not aligned to this Code of Conduct, or to ban temporarily or
|
||||
permanently any contributor for other behaviors that they deem inappropriate,
|
||||
threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces
|
||||
when an individual is representing the project or its community. Examples of
|
||||
representing a project or community include using an official project e-mail
|
||||
address, posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event. Representation of a project may be
|
||||
further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported by contacting the project team at 34790378+abhijithvijayan@users.noreply.github.com. All
|
||||
complaints will be reviewed and investigated and will result in a response that
|
||||
is deemed necessary and appropriate to the circumstances. The project team is
|
||||
obligated to maintain confidentiality with regard to the reporter of an incident.
|
||||
Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good
|
||||
faith may face temporary or permanent repercussions as determined by other
|
||||
members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
||||
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
|
||||
For answers to common questions about this code of conduct, see
|
||||
https://www.contributor-covenant.org/faq
|
||||
21
LICENCE
Normal file
21
LICENCE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) Abhijith Vijayan <email@abhijithvijayan.in> (https://abhijithvijayan.in)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
185
README.md
Normal file
185
README.md
Normal file
@ -0,0 +1,185 @@
|
||||
<h1 align="center">🚀 web-extension-starter</h1>
|
||||
<p align="center">Web Extension starter to build "Write Once Run on Any Browser" extension</p>
|
||||
<div align="center">
|
||||
<a href="https://travis-ci.com/abhijithvijayan/web-extension-starter">
|
||||
<img src="https://travis-ci.com/abhijithvijayan/web-extension-starter.svg?branch=react-typescript" alt="Travis Build" />
|
||||
</a>
|
||||
</a>
|
||||
<a href="https://david-dm.org/abhijithvijayan/web-extension-starter">
|
||||
<img src="https://img.shields.io/david/abhijithvijayan/web-extension-starter.svg?colorB=orange" alt="DEPENDENCIES" />
|
||||
</a>
|
||||
<a href="https://github.com/abhijithvijayan/web-extension-starter/blob/master/LICENSE">
|
||||
<img src="https://img.shields.io/github/license/abhijithvijayan/web-extension-starter.svg" alt="LICENSE" />
|
||||
</a>
|
||||
<a href="https://twitter.com/intent/tweet?text=Check%20out%20web-extension-starter%21%20by%20%40_abhijithv%0A%0AWeb%20Extension%20starter%20to%20build%20%22Write%20Once%20Run%20on%20Any%20Browser%22%20extension.%20https%3A%2F%2Fgithub.com%2Fabhijithvijayan%2Fweb-extension-starter%0A%0A%23javascript%20%23react%20%23typescript%20%23sass%20%23webextension%20%23chrome%20%23firefox%20%23opera">
|
||||
<img src="https://img.shields.io/twitter/url/http/shields.io.svg?style=social" alt="TWEET" />
|
||||
</a>
|
||||
</div>
|
||||
<h3 align="center">🙋♂️ Made by <a href="https://twitter.com/_abhijithv">@abhijithvijayan</a></h3>
|
||||
<p align="center">
|
||||
Donate:
|
||||
<a href="https://www.paypal.me/iamabhijithvijayan" target='_blank'><i><b>PayPal</b></i></a>,
|
||||
<a href="https://www.patreon.com/abhijithvijayan" target='_blank'><i><b>Patreon</b></i></a>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href='https://www.buymeacoffee.com/abhijithvijayan' target='_blank'>
|
||||
<img height='36' style='border:0px;height:36px;' src='https://bmc-cdn.nyc3.digitaloceanspaces.com/BMC-button-images/custom_images/orange_img.png' border='0' alt='Buy Me a Coffee' />
|
||||
</a>
|
||||
</p>
|
||||
<hr />
|
||||
|
||||
❤️ it? ⭐️ it on [GitHub](https://github.com/abhijithvijayan/web-extension-starter) or [Tweet](https://twitter.com/intent/tweet?text=Check%20out%20web-extension-starter%21%20by%20%40_abhijithv%0A%0AWeb%20Extension%20starter%20to%20build%20%22Write%20Once%20Run%20on%20Any%20Browser%22%20extension.%20https%3A%2F%2Fgithub.com%2Fabhijithvijayan%2Fweb-extension-starter%0A%0A%23javascript%20%23react%20%23typescript%20%23sass%20%23webextension%20%23chrome%20%23firefox%20%23opera) about it.
|
||||
|
||||
🧙♂️ **React + TypeScript** = [This](https://github.com/abhijithvijayan/web-extension-starter/tree/react-typescript) branch
|
||||
|
||||
😨 **React + JavaScript** = Checkout [react-javascript](https://github.com/abhijithvijayan/web-extension-starter/tree/react-javascript) branch
|
||||
|
||||
👶🏼 **HTML + JavaScript** = Checkout [master](https://github.com/abhijithvijayan/web-extension-starter/tree/master) branch
|
||||
|
||||
## Features
|
||||
|
||||
- Cross Browser Support (Web-Extensions API)
|
||||
- Browser Tailored Manifest generation
|
||||
- Automatic build on code changes
|
||||
- Auto packs browser specific build files
|
||||
- SASS styling
|
||||
- TypeScript by default
|
||||
- ES6 modules support
|
||||
- React UI Library by default
|
||||
- Smart reload
|
||||
|
||||
## Browser Support
|
||||
|
||||
| [](/) | [](/) | [](/) | [](/) | [](/) | [](/) | [](/) |
|
||||
| --------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------ |
|
||||
| 49 & later ✔ | 52 & later ✔ | 36 & later ✔ | 79 & later ✔ | Latest ✔ | Latest ✔ | Latest ✔ |
|
||||
|
||||
## Used by extensions in production that has over 100,000+ users.
|
||||
|
||||
- [daily.dev](https://daily.dev) in [daily.dev extension](https://r.daily.dev/get)
|
||||
- [Jiffy Reader](https://chrome.google.com/webstore/detail/jiffy-reader/lljedihjnnjjefafchaljkhbpfhfkdic) in [ansh/jiffyreader.com](https://github.com/ansh/jiffyreader.com)
|
||||
- [kutt-extension](https://chrome.google.com/webstore/detail/kutt/pklakpjfiegjacoppcodencchehlfnpd) in [abhijithvijayan/kutt-extension](https://github.com/abhijithvijayan/kutt-extension)
|
||||
- [doubanIMDb](https://chrome.google.com/webstore/detail/doubanimdb/nfibbjnhkbjlgjaojglmmibdjicidini) in [lisongx/doubanIMDb](https://github.com/lisongx/doubanIMDb)
|
||||
- [Mooc Assistant](https://chrome.google.com/webstore/detail/mooc-assistant/oebggekgendmoeedkkdkdcdbmfbfeldc) in [unbyte/mooc-assistant](https://github.com/unbyte/mooc-assistant)
|
||||
- ArtiPub in [crawlab-team/artipub](https://github.com/crawlab-team/artipub/tree/master/extensions)
|
||||
|
||||
and many more...
|
||||
|
||||
## Use this template
|
||||
|
||||
Create a new directory and run
|
||||
|
||||
```
|
||||
curl -fsSL https://github.com/abhijithvijayan/web-extension-starter/archive/react-typescript.tar.gz | tar -xz --strip-components=1
|
||||
```
|
||||
|
||||
## 🚀 Quick Start
|
||||
|
||||
Ensure you have
|
||||
|
||||
- [Node.js](https://nodejs.org) 10 or later installed
|
||||
- [Yarn](https://yarnpkg.com) v1 or v2 installed
|
||||
|
||||
Then run the following:
|
||||
|
||||
- `yarn install` to install dependencies.
|
||||
- `yarn run dev:chrome` to start the development server for chrome extension
|
||||
- `yarn run dev:firefox` to start the development server for firefox addon
|
||||
- `yarn run dev:opera` to start the development server for opera extension
|
||||
- `yarn run build:chrome` to build chrome extension
|
||||
- `yarn run build:firefox` to build firefox addon
|
||||
- `yarn run build:opera` to build opera extension
|
||||
- `yarn run build` builds and packs extensions all at once to extension/ directory
|
||||
|
||||
### Development
|
||||
|
||||
- `yarn install` to install dependencies.
|
||||
- To watch file changes in development
|
||||
|
||||
- Chrome
|
||||
- `yarn run dev:chrome`
|
||||
- Firefox
|
||||
- `yarn run dev:firefox`
|
||||
- Opera
|
||||
- `yarn run dev:opera`
|
||||
|
||||
- **Load extension in browser**
|
||||
|
||||
- ### Chrome
|
||||
|
||||
- Go to the browser address bar and type `chrome://extensions`
|
||||
- Check the `Developer Mode` button to enable it.
|
||||
- Click on the `Load Unpacked Extension…` button.
|
||||
- Select your browsers folder in `extension/`.
|
||||
|
||||
- ### Firefox
|
||||
|
||||
- Load the Add-on via `about:debugging` as temporary Add-on.
|
||||
- Choose the `manifest.json` file in the extracted directory
|
||||
|
||||
- ### Opera
|
||||
|
||||
- Load the extension via `opera:extensions`
|
||||
- Check the `Developer Mode` and load as unpacked from extension’s extracted directory.
|
||||
|
||||
### Production
|
||||
|
||||
- `yarn run build` builds the extension for all the browsers to `extension/BROWSER` directory respectively.
|
||||
|
||||
Note: By default the `manifest.json` is set with version `0.0.0`. The webpack loader will update the version in the build with that of the `package.json` version. In order to release a new version, update version in `package.json` and run script.
|
||||
|
||||
If you don't want to use `package.json` version, you can disable the option [here](https://github.com/abhijithvijayan/web-extension-starter/blob/e10158c4a49948dea9fdca06592876d9ca04e028/webpack.config.js#L79).
|
||||
|
||||
### Generating browser specific manifest.json
|
||||
|
||||
Update `source/manifest.json` file with browser vendor prefixed manifest keys
|
||||
|
||||
```js
|
||||
{
|
||||
"__chrome__name": "SuperChrome",
|
||||
"__firefox__name": "SuperFox",
|
||||
"__edge__name": "SuperEdge",
|
||||
"__opera__name": "SuperOpera"
|
||||
}
|
||||
```
|
||||
|
||||
if the vendor is `chrome` this compiles to:
|
||||
|
||||
```js
|
||||
{
|
||||
"name": "SuperChrome",
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Add keys to multiple vendors by separating them with | in the prefix
|
||||
|
||||
```
|
||||
{
|
||||
__chrome|opera__name: "SuperBlink"
|
||||
}
|
||||
```
|
||||
|
||||
if the vendor is `chrome` or `opera`, this compiles to:
|
||||
|
||||
```
|
||||
{
|
||||
"name": "SuperBlink"
|
||||
}
|
||||
```
|
||||
|
||||
See the original [README](https://github.com/abhijithvijayan/wext-manifest-loader) of `wext-manifest-loader` package for more details
|
||||
|
||||
## Bugs
|
||||
|
||||
Please file an issue [here](https://github.com/abhijithvijayan/web-extension-starter/issues/new) for bugs, missing documentation, or unexpected behavior.
|
||||
|
||||
### Linting & TypeScript Config
|
||||
|
||||
- Shared Eslint & Prettier Configuration - [`@abhijithvijayan/eslint-config`](https://www.npmjs.com/package/@abhijithvijayan/eslint-config)
|
||||
- Shared TypeScript Configuration - [`@abhijithvijayan/tsconfig`](https://www.npmjs.com/package/@abhijithvijayan/tsconfig)
|
||||
|
||||
## License
|
||||
|
||||
MIT © [Abhijith Vijayan](https://abhijithvijayan.in)
|
||||
88
package.json
Normal file
88
package.json
Normal file
@ -0,0 +1,88 @@
|
||||
{
|
||||
"name": "web-extension-starter",
|
||||
"version": "2.0.0",
|
||||
"description": "Web extension starter using react and typescript",
|
||||
"private": true,
|
||||
"repository": "https://github.com/abhijithvijayan/web-extension-starter.git",
|
||||
"author": {
|
||||
"name": "abhijithvijayan",
|
||||
"email": "email@abhijithvijayan.in",
|
||||
"url": "https://abhijithvijayan.in"
|
||||
},
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10.0.0",
|
||||
"yarn": ">= 1.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"dev:chrome": "cross-env NODE_ENV=development cross-env TARGET_BROWSER=chrome webpack --watch",
|
||||
"dev:firefox": "cross-env NODE_ENV=development cross-env TARGET_BROWSER=firefox webpack --watch",
|
||||
"dev:opera": "cross-env NODE_ENV=development cross-env TARGET_BROWSER=opera webpack --watch",
|
||||
"build:chrome": "cross-env NODE_ENV=production cross-env TARGET_BROWSER=chrome webpack",
|
||||
"build:firefox": "cross-env NODE_ENV=production cross-env TARGET_BROWSER=firefox webpack",
|
||||
"build:opera": "cross-env NODE_ENV=production cross-env TARGET_BROWSER=opera webpack",
|
||||
"build": "yarn run build:chrome && yarn run build:firefox && yarn run build:opera",
|
||||
"lint": "eslint . --ext .ts,.tsx",
|
||||
"lint:fix": "eslint . --ext .ts,.tsx --fix"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.14.0",
|
||||
"advanced-css-reset": "^1.2.2",
|
||||
"emoji-log": "^1.0.2",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"webext-base-css": "^1.3.1",
|
||||
"webextension-polyfill-ts": "^0.25.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@abhijithvijayan/eslint-config": "2.6.3",
|
||||
"@abhijithvijayan/eslint-config-airbnb": "^1.0.2",
|
||||
"@abhijithvijayan/tsconfig": "^1.3.0",
|
||||
"@babel/core": "^7.14.3",
|
||||
"@babel/eslint-parser": "^7.12.16",
|
||||
"@babel/plugin-proposal-class-properties": "^7.13.0",
|
||||
"@babel/plugin-proposal-object-rest-spread": "^7.14.2",
|
||||
"@babel/plugin-transform-destructuring": "^7.13.17",
|
||||
"@babel/plugin-transform-runtime": "^7.14.3",
|
||||
"@babel/preset-env": "^7.14.2",
|
||||
"@babel/preset-react": "^7.13.13",
|
||||
"@babel/preset-typescript": "^7.13.0",
|
||||
"@types/react": "^17.0.6",
|
||||
"@types/react-dom": "^17.0.5",
|
||||
"@types/webpack": "^4.41.29",
|
||||
"@typescript-eslint/eslint-plugin": "^4.4.1",
|
||||
"@typescript-eslint/parser": "^4.4.1",
|
||||
"autoprefixer": "^10.2.5",
|
||||
"babel-loader": "^8.2.2",
|
||||
"clean-webpack-plugin": "^3.0.0",
|
||||
"copy-webpack-plugin": "^6.4.1",
|
||||
"cross-env": "^7.0.3",
|
||||
"css-loader": "^5.2.5",
|
||||
"eslint": "^7.27.0",
|
||||
"eslint-config-prettier": "^6.15.0",
|
||||
"eslint-plugin-import": "^2.23.3",
|
||||
"eslint-plugin-jsx-a11y": "^6.4.1",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-prettier": "^3.4.0",
|
||||
"eslint-plugin-react": "^7.23.2",
|
||||
"eslint-plugin-react-hooks": "^4.2.0",
|
||||
"filemanager-webpack-plugin": "^3.1.1",
|
||||
"fork-ts-checker-webpack-plugin": "^6.2.10",
|
||||
"html-webpack-plugin": "^4.5.2",
|
||||
"mini-css-extract-plugin": "^1.6.0",
|
||||
"optimize-css-assets-webpack-plugin": "^5.0.6",
|
||||
"postcss": "^8.3.0",
|
||||
"postcss-loader": "^4.3.0",
|
||||
"prettier": "^2.3.0",
|
||||
"resolve-url-loader": "^3.1.3",
|
||||
"sass": "^1.53.0",
|
||||
"sass-loader": "^10.2.0",
|
||||
"terser-webpack-plugin": "^4.2.3",
|
||||
"typescript": "4.1.5",
|
||||
"webpack": "^4.46.0",
|
||||
"webpack-cli": "^4.7.0",
|
||||
"webpack-extension-reloader": "^1.1.4",
|
||||
"wext-manifest-loader": "^2.3.0",
|
||||
"wext-manifest-webpack-plugin": "^1.2.1"
|
||||
}
|
||||
}
|
||||
6
source/Background/index.ts
Normal file
6
source/Background/index.ts
Normal file
@ -0,0 +1,6 @@
|
||||
import 'emoji-log';
|
||||
import {browser} from 'webextension-polyfill-ts';
|
||||
|
||||
browser.runtime.onInstalled.addListener((): void => {
|
||||
console.emoji('🦄', 'extension installed');
|
||||
});
|
||||
3
source/ContentScript/index.ts
Normal file
3
source/ContentScript/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
console.log('helloworld from content script');
|
||||
|
||||
export {};
|
||||
34
source/Options/Options.tsx
Normal file
34
source/Options/Options.tsx
Normal file
@ -0,0 +1,34 @@
|
||||
import * as React from 'react';
|
||||
|
||||
import './styles.scss';
|
||||
|
||||
const Options: React.FC = () => {
|
||||
return (
|
||||
<div>
|
||||
<form>
|
||||
<p>
|
||||
<label htmlFor="username">Your Name</label>
|
||||
<br />
|
||||
<input
|
||||
type="text"
|
||||
id="username"
|
||||
name="username"
|
||||
spellCheck="false"
|
||||
autoComplete="off"
|
||||
required
|
||||
/>
|
||||
</p>
|
||||
<p>
|
||||
<label htmlFor="logging">
|
||||
<input type="checkbox" name="logging" /> Show the features enabled
|
||||
on each page in the console
|
||||
</label>
|
||||
|
||||
<p>cool cool cool</p>
|
||||
</p>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Options;
|
||||
6
source/Options/index.tsx
Normal file
6
source/Options/index.tsx
Normal file
@ -0,0 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
|
||||
import Options from './Options';
|
||||
|
||||
ReactDOM.render(<Options />, document.getElementById('options-root'));
|
||||
10
source/Options/styles.scss
Normal file
10
source/Options/styles.scss
Normal file
@ -0,0 +1,10 @@
|
||||
@import "../styles/fonts";
|
||||
@import "../styles/reset";
|
||||
@import "../styles/variables";
|
||||
|
||||
@import "~webext-base-css/webext-base.css";
|
||||
|
||||
body {
|
||||
color: $black;
|
||||
background-color: $greyWhite;
|
||||
}
|
||||
55
source/Popup/Popup.tsx
Normal file
55
source/Popup/Popup.tsx
Normal file
@ -0,0 +1,55 @@
|
||||
import * as React from 'react';
|
||||
import {browser, Tabs} from 'webextension-polyfill-ts';
|
||||
|
||||
import './styles.scss';
|
||||
|
||||
function openWebPage(url: string): Promise<Tabs.Tab> {
|
||||
return browser.tabs.create({url});
|
||||
}
|
||||
|
||||
const Popup: React.FC = () => {
|
||||
return (
|
||||
<section id="popup">
|
||||
<h2>WEB-EXTENSION-STARTER</h2>
|
||||
<button
|
||||
id="options__button"
|
||||
type="button"
|
||||
onClick={(): Promise<Tabs.Tab> => {
|
||||
return openWebPage('options.html');
|
||||
}}
|
||||
>
|
||||
Options Page
|
||||
</button>
|
||||
<div className="links__holder">
|
||||
<ul>
|
||||
<li>
|
||||
<button
|
||||
type="button"
|
||||
onClick={(): Promise<Tabs.Tab> => {
|
||||
return openWebPage(
|
||||
'https://github.com/abhijithvijayan/web-extension-starter'
|
||||
);
|
||||
}}
|
||||
>
|
||||
GitHub
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<button
|
||||
type="button"
|
||||
onClick={(): Promise<Tabs.Tab> => {
|
||||
return openWebPage(
|
||||
'https://www.buymeacoffee.com/abhijithvijayan'
|
||||
);
|
||||
}}
|
||||
>
|
||||
Buy Me A Coffee
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default Popup;
|
||||
6
source/Popup/index.tsx
Normal file
6
source/Popup/index.tsx
Normal file
@ -0,0 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
|
||||
import Popup from './Popup';
|
||||
|
||||
ReactDOM.render(<Popup />, document.getElementById('popup-root'));
|
||||
53
source/Popup/styles.scss
Normal file
53
source/Popup/styles.scss
Normal file
@ -0,0 +1,53 @@
|
||||
@import "../styles/fonts";
|
||||
@import "../styles/reset";
|
||||
@import "../styles/variables";
|
||||
|
||||
body {
|
||||
color: $black;
|
||||
background-color: $greyWhite;
|
||||
}
|
||||
|
||||
|
||||
#popup {
|
||||
min-width: 350px;
|
||||
padding: 30px 20px;
|
||||
|
||||
h2 {
|
||||
font-size: 25px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#options__button {
|
||||
width: 50%;
|
||||
background: green;
|
||||
color: white;
|
||||
font-weight: 500;
|
||||
border-radius: 15px;
|
||||
padding: 5px 10px;
|
||||
justify-content: center;
|
||||
margin: 20px auto;
|
||||
cursor: pointer;
|
||||
opacity: 0.8;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.links__holder {
|
||||
ul {
|
||||
display: flex;
|
||||
margin-top: 1em;
|
||||
justify-content: space-around;
|
||||
|
||||
li {
|
||||
button {
|
||||
border-radius: 25px;
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
padding: 10px 17px;
|
||||
background-color: rgba(0, 0, 255, 0.7);
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
source/assets/icons/favicon-128.png
Normal file
BIN
source/assets/icons/favicon-128.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.7 KiB |
BIN
source/assets/icons/favicon-16.png
Normal file
BIN
source/assets/icons/favicon-16.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 KiB |
BIN
source/assets/icons/favicon-32.png
Normal file
BIN
source/assets/icons/favicon-32.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
BIN
source/assets/icons/favicon-48.png
Normal file
BIN
source/assets/icons/favicon-48.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.9 KiB |
75
source/manifest.json
Normal file
75
source/manifest.json
Normal file
@ -0,0 +1,75 @@
|
||||
{
|
||||
"manifest_version": 2,
|
||||
"name": "Sample WebExtension",
|
||||
"version": "0.0.0",
|
||||
|
||||
"icons": {
|
||||
"16": "assets/icons/favicon-16.png",
|
||||
"32": "assets/icons/favicon-32.png",
|
||||
"48": "assets/icons/favicon-48.png",
|
||||
"128": "assets/icons/favicon-128.png"
|
||||
},
|
||||
"description": "Sample description",
|
||||
"homepage_url": "https://github.com/abhijithvijayan/web-extension-starter",
|
||||
"short_name": "Sample Name",
|
||||
|
||||
"permissions": [
|
||||
"activeTab",
|
||||
"storage",
|
||||
"http://*/*",
|
||||
"https://*/*"
|
||||
],
|
||||
|
||||
"content_security_policy": "script-src 'self'; object-src 'self'",
|
||||
|
||||
"__chrome|firefox__author": "abhijithvijayan",
|
||||
"__opera__developer": {
|
||||
"name": "abhijithvijayan"
|
||||
},
|
||||
|
||||
"__firefox__applications": {
|
||||
"gecko": {
|
||||
"id": "{754FB1AD-CC3B-4856-B6A0-7786F8CA9D17}"
|
||||
}
|
||||
},
|
||||
|
||||
"__chrome__minimum_chrome_version": "49",
|
||||
"__opera__minimum_opera_version": "36",
|
||||
|
||||
"browser_action": {
|
||||
"default_popup": "popup.html",
|
||||
"default_icon": {
|
||||
"16": "assets/icons/favicon-16.png",
|
||||
"32": "assets/icons/favicon-32.png",
|
||||
"48": "assets/icons/favicon-48.png",
|
||||
"128": "assets/icons/favicon-128.png"
|
||||
},
|
||||
"default_title": "tiny title",
|
||||
"__chrome|opera__chrome_style": false,
|
||||
"__firefox__browser_style": false
|
||||
},
|
||||
|
||||
"__chrome|opera__options_page": "options.html",
|
||||
"options_ui": {
|
||||
"page": "options.html",
|
||||
"open_in_tab": true,
|
||||
"__chrome__chrome_style": false
|
||||
},
|
||||
|
||||
"background": {
|
||||
"scripts": [
|
||||
"js/background.bundle.js"
|
||||
],
|
||||
"__chrome|opera__persistent": false
|
||||
},
|
||||
|
||||
"content_scripts": [{
|
||||
"matches": [
|
||||
"http://*/*",
|
||||
"https://*/*"
|
||||
],
|
||||
"js": [
|
||||
"js/contentScript.bundle.js"
|
||||
]
|
||||
}]
|
||||
}
|
||||
1
source/styles/_fonts.scss
Normal file
1
source/styles/_fonts.scss
Normal file
@ -0,0 +1 @@
|
||||
@import url("https://fonts.googleapis.com/css?family=Nunito:400,600");
|
||||
10
source/styles/_reset.scss
Normal file
10
source/styles/_reset.scss
Normal file
@ -0,0 +1,10 @@
|
||||
@import '~advanced-css-reset/dist/reset.css';
|
||||
|
||||
// Add your custom reset rules here
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
outline: 0;
|
||||
}
|
||||
23
source/styles/_variables.scss
Normal file
23
source/styles/_variables.scss
Normal file
@ -0,0 +1,23 @@
|
||||
// colors
|
||||
$black: #0d0d0d;
|
||||
$greyWhite: #f3f3f3;
|
||||
$skyBlue: #8892b0;
|
||||
|
||||
// fonts
|
||||
$nunito: "Nunito", sans-serif;
|
||||
|
||||
// font weights
|
||||
$thin: 100;
|
||||
$exlight: 200;
|
||||
$light: 300;
|
||||
$regular: 400;
|
||||
$medium: 500;
|
||||
$semibold: 600;
|
||||
$bold: 700;
|
||||
$exbold: 800;
|
||||
$exblack: 900;
|
||||
|
||||
// other variables
|
||||
.d-none {
|
||||
display: none !important;
|
||||
}
|
||||
21
tsconfig.json
Normal file
21
tsconfig.json
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"extends": "@abhijithvijayan/tsconfig",
|
||||
"compilerOptions": {
|
||||
"target": "es5", // ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'.
|
||||
"module": "esnext", // Module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'.
|
||||
"lib": [
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"esnext"
|
||||
],
|
||||
"declaration": false,
|
||||
"isolatedModules": true,
|
||||
/* Additional Checks */
|
||||
"useDefineForClassFields": true,
|
||||
"skipLibCheck": true,
|
||||
},
|
||||
"include": [
|
||||
"source",
|
||||
"webpack.config.js"
|
||||
]
|
||||
}
|
||||
11
views/options.html
Normal file
11
views/options.html
Normal file
@ -0,0 +1,11 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Options</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="options-root"></div>
|
||||
</body>
|
||||
</html>
|
||||
11
views/popup.html
Normal file
11
views/popup.html
Normal file
@ -0,0 +1,11 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=500" />
|
||||
<title>Popup</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="popup-root"></div>
|
||||
</body>
|
||||
</html>
|
||||
211
webpack.config.js
Normal file
211
webpack.config.js
Normal file
@ -0,0 +1,211 @@
|
||||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
const FilemanagerPlugin = require('filemanager-webpack-plugin');
|
||||
const TerserPlugin = require('terser-webpack-plugin');
|
||||
const CopyWebpackPlugin = require('copy-webpack-plugin');
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
|
||||
const ExtensionReloader = require('webpack-extension-reloader');
|
||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
||||
const WextManifestWebpackPlugin = require('wext-manifest-webpack-plugin');
|
||||
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
|
||||
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
|
||||
|
||||
const viewsPath = path.join(__dirname, 'views');
|
||||
const sourcePath = path.join(__dirname, 'source');
|
||||
const destPath = path.join(__dirname, 'extension');
|
||||
const nodeEnv = process.env.NODE_ENV || 'development';
|
||||
const targetBrowser = process.env.TARGET_BROWSER;
|
||||
|
||||
const extensionReloaderPlugin =
|
||||
nodeEnv === 'development'
|
||||
? new ExtensionReloader({
|
||||
port: 9090,
|
||||
reloadPage: true,
|
||||
entries: {
|
||||
// TODO: reload manifest on update
|
||||
contentScript: 'contentScript',
|
||||
background: 'background',
|
||||
extensionPage: ['popup', 'options'],
|
||||
},
|
||||
})
|
||||
: () => {
|
||||
this.apply = () => {};
|
||||
};
|
||||
|
||||
const getExtensionFileType = (browser) => {
|
||||
if (browser === 'opera') {
|
||||
return 'crx';
|
||||
}
|
||||
|
||||
if (browser === 'firefox') {
|
||||
return 'xpi';
|
||||
}
|
||||
|
||||
return 'zip';
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
devtool: false, // https://github.com/webpack/webpack/issues/1194#issuecomment-560382342
|
||||
|
||||
stats: {
|
||||
all: false,
|
||||
builtAt: true,
|
||||
errors: true,
|
||||
hash: true,
|
||||
},
|
||||
|
||||
mode: nodeEnv,
|
||||
|
||||
entry: {
|
||||
manifest: path.join(sourcePath, 'manifest.json'),
|
||||
background: path.join(sourcePath, 'Background', 'index.ts'),
|
||||
contentScript: path.join(sourcePath, 'ContentScript', 'index.ts'),
|
||||
popup: path.join(sourcePath, 'Popup', 'index.tsx'),
|
||||
options: path.join(sourcePath, 'Options', 'index.tsx'),
|
||||
},
|
||||
|
||||
output: {
|
||||
path: path.join(destPath, targetBrowser),
|
||||
filename: 'js/[name].bundle.js',
|
||||
},
|
||||
|
||||
resolve: {
|
||||
extensions: ['.ts', '.tsx', '.js', '.json'],
|
||||
alias: {
|
||||
'webextension-polyfill-ts': path.resolve(
|
||||
path.join(__dirname, 'node_modules', 'webextension-polyfill-ts')
|
||||
),
|
||||
},
|
||||
},
|
||||
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
type: 'javascript/auto', // prevent webpack handling json with its own loaders,
|
||||
test: /manifest\.json$/,
|
||||
use: {
|
||||
loader: 'wext-manifest-loader',
|
||||
options: {
|
||||
usePackageJSONVersion: true, // set to false to not use package.json version for manifest
|
||||
},
|
||||
},
|
||||
exclude: /node_modules/,
|
||||
},
|
||||
{
|
||||
test: /\.(js|ts)x?$/,
|
||||
loader: 'babel-loader',
|
||||
exclude: /node_modules/,
|
||||
},
|
||||
{
|
||||
test: /\.(sa|sc|c)ss$/,
|
||||
use: [
|
||||
{
|
||||
loader: MiniCssExtractPlugin.loader, // It creates a CSS file per JS file which contains CSS
|
||||
},
|
||||
{
|
||||
loader: 'css-loader', // Takes the CSS files and returns the CSS with imports and url(...) for Webpack
|
||||
options: {
|
||||
sourceMap: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
loader: 'postcss-loader',
|
||||
options: {
|
||||
postcssOptions: {
|
||||
plugins: [
|
||||
[
|
||||
'autoprefixer',
|
||||
{
|
||||
// Options
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
'resolve-url-loader', // Rewrites relative paths in url() statements
|
||||
'sass-loader', // Takes the Sass/SCSS file and compiles to the CSS
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
plugins: [
|
||||
// Plugin to not generate js bundle for manifest entry
|
||||
new WextManifestWebpackPlugin(),
|
||||
// Generate sourcemaps
|
||||
new webpack.SourceMapDevToolPlugin({filename: false}),
|
||||
new ForkTsCheckerWebpackPlugin(),
|
||||
// environmental variables
|
||||
new webpack.EnvironmentPlugin(['NODE_ENV', 'TARGET_BROWSER']),
|
||||
// delete previous build files
|
||||
new CleanWebpackPlugin({
|
||||
cleanOnceBeforeBuildPatterns: [
|
||||
path.join(process.cwd(), `extension/${targetBrowser}`),
|
||||
path.join(
|
||||
process.cwd(),
|
||||
`extension/${targetBrowser}.${getExtensionFileType(targetBrowser)}`
|
||||
),
|
||||
],
|
||||
cleanStaleWebpackAssets: false,
|
||||
verbose: true,
|
||||
}),
|
||||
new HtmlWebpackPlugin({
|
||||
template: path.join(viewsPath, 'popup.html'),
|
||||
inject: 'body',
|
||||
chunks: ['popup'],
|
||||
hash: true,
|
||||
filename: 'popup.html',
|
||||
}),
|
||||
new HtmlWebpackPlugin({
|
||||
template: path.join(viewsPath, 'options.html'),
|
||||
inject: 'body',
|
||||
chunks: ['options'],
|
||||
hash: true,
|
||||
filename: 'options.html',
|
||||
}),
|
||||
// write css file(s) to build folder
|
||||
new MiniCssExtractPlugin({filename: 'css/[name].css'}),
|
||||
// copy static assets
|
||||
new CopyWebpackPlugin({
|
||||
patterns: [{from: 'source/assets', to: 'assets'}],
|
||||
}),
|
||||
// plugin to enable browser reloading in development mode
|
||||
extensionReloaderPlugin,
|
||||
],
|
||||
|
||||
optimization: {
|
||||
minimize: true,
|
||||
minimizer: [
|
||||
new TerserPlugin({
|
||||
parallel: true,
|
||||
terserOptions: {
|
||||
format: {
|
||||
comments: false,
|
||||
},
|
||||
},
|
||||
extractComments: false,
|
||||
}),
|
||||
new OptimizeCSSAssetsPlugin({
|
||||
cssProcessorPluginOptions: {
|
||||
preset: ['default', {discardComments: {removeAll: true}}],
|
||||
},
|
||||
}),
|
||||
new FilemanagerPlugin({
|
||||
events: {
|
||||
onEnd: {
|
||||
archive: [
|
||||
{
|
||||
format: 'zip',
|
||||
source: path.join(destPath, targetBrowser),
|
||||
destination: `${path.join(destPath, targetBrowser)}.${getExtensionFileType(targetBrowser)}`,
|
||||
options: {zlib: {level: 6}},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
}),
|
||||
],
|
||||
},
|
||||
};
|
||||
Loading…
x
Reference in New Issue
Block a user