mirror of
https://github.com/tlsnotary/tlsn-extension.git
synced 2026-01-09 15:18:09 -05:00
commit boilerplate
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -5,3 +5,5 @@ bin/
|
||||
pkg/
|
||||
wasm-pack.log
|
||||
**/node_modules
|
||||
**/.DS_Store
|
||||
.idea
|
||||
|
||||
173
README.md
Normal file → Executable file
173
README.md
Normal file → Executable file
@@ -1,63 +1,150 @@
|
||||
# tlsn-extension 🚧🚧🚧
|
||||
<img src="src/assets/img/icon-128.png" width="64"/>
|
||||
|
||||
## Bind a rust websocket client
|
||||
We used the example from [wasm-bindgen](https://rustwasm.github.io/docs/wasm-bindgen/examples/websockets.html) with the following changes:
|
||||
1. Use webpack to bundle the javascript
|
||||
2. Add a websocket server to listen to the messages from the browser
|
||||
# Chrome Extension (MV3) Boilerplate with React 18 and Webpack 5
|
||||
|
||||
[](https://www.npmjs.com/package/chrome-extension-boilerplate-react)
|
||||
[](https://www.npmjs.com/package/chrome-extension-boilerplate-react)
|
||||
[](https://www.npmjs.com/package/chrome-extension-boilerplate-react)
|
||||
|
||||
### Install `wasm-pack`
|
||||
Do it with `yarn`, or you can install it in [other ways](https://rustwasm.github.io/wasm-pack/installer/).
|
||||
## Announcements
|
||||
|
||||
```bash
|
||||
yarn global add wasm-pack
|
||||
- Recently updated from **[React](https://reactjs.org)** ~~17~~ to **18**!
|
||||
- **_This boilerplate adopts [Manifest V3](https://developer.chrome.com/docs/extensions/mv3/intro/mv3-overview/)!_**
|
||||
- For V2 users, please check out the [manifest-v2](https://github.com/lxieyang/chrome-extension-boilerplate-react/tree/manifest-v2) branch, or use version [3.x](https://www.npmjs.com/package/chrome-extension-boilerplate-react/v/3.3.0).
|
||||
- Check out the [Manifest V3 Migration Guide](https://developer.chrome.com/docs/extensions/mv3/intro/mv3-migration/).
|
||||
- Recently added [devtools](https://developer.chrome.com/docs/extensions/mv3/devtools/) Support! Thanks [GeekaholicLin](https://github.com/lxieyang/chrome-extension-boilerplate-react/issues/17)!
|
||||
- Recently updated from **[Webpack Dev Server](https://webpack.js.org/configuration/dev-server/)** ~~3.x~~ to **4.x** and **[Webpack](https://webpack.js.org/)** ~~4~~ to **5**!
|
||||
- Recently added [TypeScript](https://www.typescriptlang.org/) Support!
|
||||
|
||||
## Features
|
||||
|
||||
This is a basic Chrome Extensions boilerplate to help you write modular and modern Javascript code, load CSS easily and [automatic reload the browser on code changes](https://webpack.github.io/docs/webpack-dev-server.html#automatic-refresh).
|
||||
|
||||
This boilerplate is updated with:
|
||||
|
||||
- [Chrome Extension Manifest V3](https://developer.chrome.com/docs/extensions/mv3/intro/mv3-overview/)
|
||||
- [React 18](https://reactjs.org)
|
||||
- [Webpack 5](https://webpack.js.org/)
|
||||
- [Webpack Dev Server 4](https://webpack.js.org/configuration/dev-server/)
|
||||
- [React Refresh](https://www.npmjs.com/package/react-refresh)
|
||||
- [react-refresh-webpack-plugin](https://github.com/pmmmwh/react-refresh-webpack-plugin)
|
||||
- [eslint-config-react-app](https://www.npmjs.com/package/eslint-config-react-app)
|
||||
- [Prettier](https://prettier.io/)
|
||||
- [TypeScript](https://www.typescriptlang.org/)
|
||||
|
||||
This boilerplate is heavily inspired by and adapted from [https://github.com/samuelsimoes/chrome-extension-webpack-boilerplate](https://github.com/samuelsimoes/chrome-extension-webpack-boilerplate), with additional support for React 18 features, Webpack 5, and Webpack Dev Server 4.
|
||||
|
||||
Please open up an issue to nudge me to keep the npm packages up-to-date. FYI, it takes time to make different packages with different versions work together nicely.
|
||||
|
||||
## Installing and Running
|
||||
|
||||
### Procedures:
|
||||
|
||||
1. Check if your [Node.js](https://nodejs.org/) version is >= **18**.
|
||||
2. Clone this repository.
|
||||
3. Change the package's `name`, `description`, and `repository` fields in `package.json`.
|
||||
4. Change the name of your extension on `src/manifest.json`.
|
||||
5. Run `npm install` to install the dependencies.
|
||||
6. Run `npm start`
|
||||
7. Load your extension on Chrome following:
|
||||
1. Access `chrome://extensions/`
|
||||
2. Check `Developer mode`
|
||||
3. Click on `Load unpacked extension`
|
||||
4. Select the `build` folder.
|
||||
8. Happy hacking.
|
||||
|
||||
## Structure
|
||||
|
||||
All your extension's code must be placed in the `src` folder.
|
||||
|
||||
The boilerplate is already prepared to have a popup, an options page, a background page, and a new tab page (which replaces the new tab page of your browser). But feel free to customize these.
|
||||
|
||||
## TypeScript
|
||||
|
||||
This boilerplate now supports TypeScript! The `Options` Page is implemented using TypeScript. Please refer to `src/pages/Options/` for example usages.
|
||||
|
||||
## Webpack auto-reload and HRM
|
||||
|
||||
To make your workflow much more efficient this boilerplate uses the [webpack server](https://webpack.github.io/docs/webpack-dev-server.html) to development (started with `npm start`) with auto reload feature that reloads the browser automatically every time that you save some file in your editor.
|
||||
|
||||
You can run the dev mode on other port if you want. Just specify the env var `port` like this:
|
||||
|
||||
```
|
||||
$ PORT=6002 npm run start
|
||||
```
|
||||
|
||||
### Compile rust to wasm and create a JS package binding
|
||||
## Content Scripts
|
||||
|
||||
```bash
|
||||
yarn build-rs
|
||||
Although this boilerplate uses the webpack dev server, it's also prepared to write all your bundles files on the disk at every code change, so you can point, on your extension manifest, to your bundles that you want to use as [content scripts](https://developer.chrome.com/extensions/content_scripts), but you need to exclude these entry points from hot reloading [(why?)](https://github.com/samuelsimoes/chrome-extension-webpack-boilerplate/issues/4#issuecomment-261788690). To do so you need to expose which entry points are content scripts on the `webpack.config.js` using the `chromeExtensionBoilerplate -> notHotReload` config. Look the example below.
|
||||
|
||||
Let's say that you want use the `myContentScript` entry point as content script, so on your `webpack.config.js` you will configure the entry point and exclude it from hot reloading, like this:
|
||||
|
||||
```js
|
||||
{
|
||||
…
|
||||
entry: {
|
||||
myContentScript: "./src/js/myContentScript.js"
|
||||
},
|
||||
chromeExtensionBoilerplate: {
|
||||
notHotReload: ["myContentScript"]
|
||||
}
|
||||
…
|
||||
}
|
||||
```
|
||||
|
||||
You can see the resulting JS package in `pkg/`.
|
||||
and on your `src/manifest.json`:
|
||||
|
||||
```bash
|
||||
tree pkg
|
||||
pkg
|
||||
├── README.md
|
||||
├── package.json
|
||||
├── tlsn_extension_rs.d.ts
|
||||
├── tlsn_extension_rs.js
|
||||
├── tlsn_extension_rs_bg.wasm
|
||||
└── tlsn_extension_rs_bg.wasm.d.ts
|
||||
```json
|
||||
{
|
||||
"content_scripts": [
|
||||
{
|
||||
"matches": ["https://www.google.com/*"],
|
||||
"js": ["myContentScript.bundle.js"]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Install dependencies
|
||||
## Intelligent Code Completion
|
||||
|
||||
```bash
|
||||
yarn install
|
||||
Thanks to [@hudidit](https://github.com/lxieyang/chrome-extension-boilerplate-react/issues/4)'s kind suggestions, this boilerplate supports chrome-specific intelligent code completion using [@types/chrome](https://www.npmjs.com/package/@types/chrome).
|
||||
|
||||
## Packing
|
||||
|
||||
After the development of your extension run the command
|
||||
|
||||
```
|
||||
$ NODE_ENV=production npm run build
|
||||
```
|
||||
|
||||
### Run the websocket server in another terminal
|
||||
Open a new terminal and run the websocket server
|
||||
```bash
|
||||
yarn ws-server
|
||||
Now, the content of `build` folder will be the extension ready to be submitted to the Chrome Web Store. Just take a look at the [official guide](https://developer.chrome.com/webstore/publish) to more infos about publishing.
|
||||
|
||||
## Secrets
|
||||
|
||||
If you are developing an extension that talks with some API you probably are using different keys for testing and production. Is a good practice you not commit your secret keys and expose to anyone that have access to the repository.
|
||||
|
||||
To this task this boilerplate import the file `./secrets.<THE-NODE_ENV>.js` on your modules through the module named as `secrets`, so you can do things like this:
|
||||
|
||||
_./secrets.development.js_
|
||||
|
||||
```js
|
||||
export default { key: '123' };
|
||||
```
|
||||
|
||||
### Run the web server
|
||||
```bash
|
||||
yarn start
|
||||
_./src/popup.js_
|
||||
|
||||
```js
|
||||
import secrets from 'secrets';
|
||||
ApiCall({ key: secrets.key });
|
||||
```
|
||||
|
||||
### Open the browser
|
||||
```bash
|
||||
open http://localhost:8080
|
||||
```
|
||||
:point_right: The files with name `secrets.*.js` already are ignored on the repository.
|
||||
|
||||
And you should see outputs from the browser console:
|
||||
```
|
||||
socket opened
|
||||
tlsn_extension_rs.js:278 message successfully sent
|
||||
tlsn_extension_rs.js:278 binary message successfully sent
|
||||
tlsn_extension_rs.js:278 message event, received Text: "something"
|
||||
```
|
||||
## Resources:
|
||||
|
||||
- [Webpack documentation](https://webpack.js.org/concepts/)
|
||||
- [Chrome Extension documentation](https://developer.chrome.com/extensions/getstarted)
|
||||
|
||||
---
|
||||
|
||||
Michael Xieyang Liu | [Website](https://lxieyang.github.io)
|
||||
|
||||
5
bootstrap.js
vendored
5
bootstrap.js
vendored
@@ -1,5 +0,0 @@
|
||||
// A dependency graph that contains any wasm must all be imported
|
||||
// asynchronously. This `bootstrap.js` file does the single async import, so
|
||||
// that no one else needs to worry about it again.
|
||||
import("./index.js")
|
||||
.catch(e => console.error("Error importing `index.js`:", e));
|
||||
10
index.html
10
index.html
@@ -1,10 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>WebSockets example</title>
|
||||
<script src="bootstrap.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
65
package.json
Normal file → Executable file
65
package.json
Normal file → Executable file
@@ -1,25 +1,60 @@
|
||||
{
|
||||
"name": "tlsn-extension",
|
||||
"version": "0.0.1",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"build-rs": "wasm-pack build --target web",
|
||||
"build": "webpack --config webpack.config.js",
|
||||
"start": "webpack-dev-server",
|
||||
"build-and-start": "yarn build-rs && yarn install && yarn start",
|
||||
"clean": "rm -rf pkg/ node_modules/ dist/ yarn.lock"
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/tlsnotary/tlsn-extension.git"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "node utils/build.js",
|
||||
"start": "node utils/webserver.js",
|
||||
"prettier": "prettier --write '**/*.{js,jsx,ts,tsx,json,css,scss,md}'"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"comlink": "^4.4.1",
|
||||
"tlsn-extension-rs": "file:./pkg"
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.20.12",
|
||||
"@babel/plugin-proposal-class-properties": "^7.18.6",
|
||||
"@babel/preset-env": "^7.20.2",
|
||||
"@babel/preset-react": "^7.18.6",
|
||||
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.10",
|
||||
"@types/chrome": "^0.0.202",
|
||||
"@types/react": "^18.0.26",
|
||||
"@types/react-dom": "^18.0.10",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"babel-loader": "^9.1.2",
|
||||
"babel-preset-react-app": "^10.0.1",
|
||||
"clean-webpack-plugin": "^4.0.0",
|
||||
"copy-webpack-plugin": "^11.0.0",
|
||||
"webpack": "^5.88.1",
|
||||
"webpack-cli": "^5.1.4",
|
||||
"webpack-dev-server": "^4.15.1"
|
||||
"css-loader": "^6.7.3",
|
||||
"eslint": "^8.31.0",
|
||||
"eslint-config-react-app": "^7.0.1",
|
||||
"eslint-plugin-flowtype": "^8.0.3",
|
||||
"eslint-plugin-import": "^2.27.4",
|
||||
"eslint-plugin-jsx-a11y": "^6.7.1",
|
||||
"eslint-plugin-react": "^7.32.0",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"file-loader": "^6.2.0",
|
||||
"fs-extra": "^11.1.0",
|
||||
"html-loader": "^4.2.0",
|
||||
"html-webpack-plugin": "^5.5.0",
|
||||
"prettier": "^2.8.3",
|
||||
"react-refresh": "^0.14.0",
|
||||
"react-refresh-typescript": "^2.0.7",
|
||||
"sass": "^1.57.1",
|
||||
"sass-loader": "^13.2.0",
|
||||
"source-map-loader": "^3.0.1",
|
||||
"style-loader": "^3.3.1",
|
||||
"terser-webpack-plugin": "^5.3.6",
|
||||
"ts-loader": "^9.4.2",
|
||||
"type-fest": "^3.5.2",
|
||||
"typescript": "^4.9.4",
|
||||
"webpack": "^5.75.0",
|
||||
"webpack-cli": "^4.10.0",
|
||||
"webpack-dev-server": "^4.11.1",
|
||||
"zip-webpack-plugin": "^4.0.1"
|
||||
}
|
||||
}
|
||||
|
||||
BIN
src/assets/img/icon-128.png
Normal file
BIN
src/assets/img/icon-128.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
BIN
src/assets/img/icon-34.png
Normal file
BIN
src/assets/img/icon-34.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.2 KiB |
7
src/assets/img/logo.svg
Normal file
7
src/assets/img/logo.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3">
|
||||
<g fill="#61DAFB">
|
||||
<path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/>
|
||||
<circle cx="420.9" cy="296.5" r="45.7"/>
|
||||
<path d="M520.5 78.1z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.6 KiB |
19
src/containers/Greetings/Greetings.jsx
Normal file
19
src/containers/Greetings/Greetings.jsx
Normal file
@@ -0,0 +1,19 @@
|
||||
import React, { Component } from 'react';
|
||||
import icon from '../../assets/img/icon-128.png';
|
||||
|
||||
class GreetingComponent extends Component {
|
||||
state = {
|
||||
name: 'dev',
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<p>Hello, {this.state.name}!</p>
|
||||
<img src={icon} alt="extension icon" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default GreetingComponent;
|
||||
31
src/manifest.json
Executable file
31
src/manifest.json
Executable file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"manifest_version": 3,
|
||||
"name": "TLSN Extension",
|
||||
"description": "A chrome extension for TLSN",
|
||||
"options_page": "options.html",
|
||||
"background": { "service_worker": "background.bundle.js" },
|
||||
"action": {
|
||||
"default_popup": "popup.html",
|
||||
"default_icon": "icon-34.png"
|
||||
},
|
||||
"chrome_url_overrides": {
|
||||
"newtab": "newtab.html"
|
||||
},
|
||||
"icons": {
|
||||
"128": "icon-128.png"
|
||||
},
|
||||
"content_scripts": [
|
||||
{
|
||||
"matches": ["http://*/*", "https://*/*", "<all_urls>"],
|
||||
"js": ["contentScript.bundle.js"],
|
||||
"css": ["content.styles.css"]
|
||||
}
|
||||
],
|
||||
"devtools_page": "devtools.html",
|
||||
"web_accessible_resources": [
|
||||
{
|
||||
"resources": ["content.styles.css", "icon-128.png", "icon-34.png"],
|
||||
"matches": []
|
||||
}
|
||||
]
|
||||
}
|
||||
2
src/pages/Background/index.js
Normal file
2
src/pages/Background/index.js
Normal file
@@ -0,0 +1,2 @@
|
||||
console.log('This is the background page.');
|
||||
console.log('Put the background scripts here.');
|
||||
0
src/pages/Content/content.styles.css
Normal file
0
src/pages/Content/content.styles.css
Normal file
6
src/pages/Content/index.js
Normal file
6
src/pages/Content/index.js
Normal file
@@ -0,0 +1,6 @@
|
||||
import { printLine } from './modules/print';
|
||||
|
||||
console.log('Content script works!');
|
||||
console.log('Must reload extension for modifications to take effect.');
|
||||
|
||||
printLine("Using the 'printLine' function from the Print Module");
|
||||
3
src/pages/Content/modules/print.js
Normal file
3
src/pages/Content/modules/print.js
Normal file
@@ -0,0 +1,3 @@
|
||||
export const printLine = (line) => {
|
||||
console.log('===> FROM THE PRINT MODULE:', line);
|
||||
};
|
||||
9
src/pages/Devtools/index.html
Normal file
9
src/pages/Devtools/index.html
Normal file
@@ -0,0 +1,9 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title></title>
|
||||
</head>
|
||||
|
||||
<body></body>
|
||||
</html>
|
||||
5
src/pages/Devtools/index.js
Normal file
5
src/pages/Devtools/index.js
Normal file
@@ -0,0 +1,5 @@
|
||||
chrome.devtools.panels.create(
|
||||
'Dev Tools from chrome-extension-boilerplate-react',
|
||||
'icon-34.png',
|
||||
'panel.html'
|
||||
);
|
||||
38
src/pages/Newtab/Newtab.css
Normal file
38
src/pages/Newtab/Newtab.css
Normal file
@@ -0,0 +1,38 @@
|
||||
.App {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.App-logo {
|
||||
height: 40vmin;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
.App-logo {
|
||||
animation: App-logo-spin infinite 20s linear;
|
||||
}
|
||||
}
|
||||
|
||||
.App-header {
|
||||
background-color: #282c34;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: calc(10px + 2vmin);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.App-link {
|
||||
color: #61dafb;
|
||||
}
|
||||
|
||||
@keyframes App-logo-spin {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
28
src/pages/Newtab/Newtab.jsx
Normal file
28
src/pages/Newtab/Newtab.jsx
Normal file
@@ -0,0 +1,28 @@
|
||||
import React from 'react';
|
||||
import logo from '../../assets/img/logo.svg';
|
||||
import './Newtab.css';
|
||||
import './Newtab.scss';
|
||||
|
||||
const Newtab = () => {
|
||||
return (
|
||||
<div className="App">
|
||||
<header className="App-header">
|
||||
<img src={logo} className="App-logo" alt="logo" />
|
||||
<p>
|
||||
Edit <code>src/pages/Newtab/Newtab.js</code> and save to reload.
|
||||
</p>
|
||||
<a
|
||||
className="App-link"
|
||||
href="https://reactjs.org"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Learn React!
|
||||
</a>
|
||||
<h6>The color of this paragraph is defined using SASS.</h6>
|
||||
</header>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Newtab;
|
||||
10
src/pages/Newtab/Newtab.scss
Normal file
10
src/pages/Newtab/Newtab.scss
Normal file
@@ -0,0 +1,10 @@
|
||||
$myColor: orange;
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
color: $myColor;
|
||||
}
|
||||
13
src/pages/Newtab/index.css
Normal file
13
src/pages/Newtab/index.css
Normal file
@@ -0,0 +1,13 @@
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
||||
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
||||
sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
||||
monospace;
|
||||
}
|
||||
12
src/pages/Newtab/index.html
Normal file
12
src/pages/Newtab/index.html
Normal file
@@ -0,0 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>Chrome Extension Boilerplate (with React 16.6+ & Webpack 4+)</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app-container"></div>
|
||||
</body>
|
||||
</html>
|
||||
9
src/pages/Newtab/index.jsx
Normal file
9
src/pages/Newtab/index.jsx
Normal file
@@ -0,0 +1,9 @@
|
||||
import React from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
|
||||
import Newtab from './Newtab';
|
||||
import './index.css';
|
||||
|
||||
const container = document.getElementById('app-container');
|
||||
const root = createRoot(container); // createRoot(container!) if you use TypeScript
|
||||
root.render(<Newtab />);
|
||||
8
src/pages/Options/Options.css
Normal file
8
src/pages/Options/Options.css
Normal file
@@ -0,0 +1,8 @@
|
||||
.OptionsContainer {
|
||||
width: 100%;
|
||||
height: 50vh;
|
||||
font-size: 2rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
12
src/pages/Options/Options.tsx
Normal file
12
src/pages/Options/Options.tsx
Normal file
@@ -0,0 +1,12 @@
|
||||
import React from 'react';
|
||||
import './Options.css';
|
||||
|
||||
interface Props {
|
||||
title: string;
|
||||
}
|
||||
|
||||
const Options: React.FC<Props> = ({ title }: Props) => {
|
||||
return <div className="OptionsContainer">{title} Page</div>;
|
||||
};
|
||||
|
||||
export default Options;
|
||||
0
src/pages/Options/index.css
Normal file
0
src/pages/Options/index.css
Normal file
12
src/pages/Options/index.html
Normal file
12
src/pages/Options/index.html
Normal file
@@ -0,0 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>Settings</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app-container"></div>
|
||||
</body>
|
||||
</html>
|
||||
9
src/pages/Options/index.jsx
Normal file
9
src/pages/Options/index.jsx
Normal file
@@ -0,0 +1,9 @@
|
||||
import React from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
|
||||
import Options from './Options';
|
||||
import './index.css';
|
||||
|
||||
const container = document.getElementById('app-container');
|
||||
const root = createRoot(container); // createRoot(container!) if you use TypeScript
|
||||
root.render(<Options title={'Settings'} />);
|
||||
7
src/pages/Panel/Panel.css
Normal file
7
src/pages/Panel/Panel.css
Normal file
@@ -0,0 +1,7 @@
|
||||
body {
|
||||
background-color: #242424;
|
||||
}
|
||||
|
||||
.container {
|
||||
color: #ffffff;
|
||||
}
|
||||
12
src/pages/Panel/Panel.tsx
Normal file
12
src/pages/Panel/Panel.tsx
Normal file
@@ -0,0 +1,12 @@
|
||||
import React from 'react';
|
||||
import './Panel.css';
|
||||
|
||||
const Panel: React.FC = () => {
|
||||
return (
|
||||
<div className="container">
|
||||
<h1>Dev Tools Panel</h1>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Panel;
|
||||
0
src/pages/Panel/index.css
Normal file
0
src/pages/Panel/index.css
Normal file
12
src/pages/Panel/index.html
Normal file
12
src/pages/Panel/index.html
Normal file
@@ -0,0 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>Dev Tools Panel</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app-container"></div>
|
||||
</body>
|
||||
</html>
|
||||
9
src/pages/Panel/index.jsx
Normal file
9
src/pages/Panel/index.jsx
Normal file
@@ -0,0 +1,9 @@
|
||||
import React from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
|
||||
import Panel from './Panel';
|
||||
import './index.css';
|
||||
|
||||
const container = document.getElementById('app-container');
|
||||
const root = createRoot(container); // createRoot(container!) if you use TypeScript
|
||||
root.render(<Panel />);
|
||||
45
src/pages/Popup/Popup.css
Normal file
45
src/pages/Popup/Popup.css
Normal file
@@ -0,0 +1,45 @@
|
||||
.App {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
bottom: 0px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
padding: 10px;
|
||||
background-color: #282c34;
|
||||
}
|
||||
|
||||
.App-logo {
|
||||
height: 30vmin;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
.App-logo {
|
||||
animation: App-logo-spin infinite 20s linear;
|
||||
}
|
||||
}
|
||||
|
||||
.App-header {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: calc(10px + 2vmin);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.App-link {
|
||||
color: #61dafb;
|
||||
}
|
||||
|
||||
@keyframes App-logo-spin {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
27
src/pages/Popup/Popup.jsx
Normal file
27
src/pages/Popup/Popup.jsx
Normal file
@@ -0,0 +1,27 @@
|
||||
import React from 'react';
|
||||
import logo from '../../assets/img/logo.svg';
|
||||
import Greetings from '../../containers/Greetings/Greetings';
|
||||
import './Popup.css';
|
||||
|
||||
const Popup = () => {
|
||||
return (
|
||||
<div className="App">
|
||||
<header className="App-header">
|
||||
<img src={logo} className="App-logo" alt="logo" />
|
||||
<p>
|
||||
Edit <code>src/pages/Popup/Popup.jsx</code> and save to reload.
|
||||
</p>
|
||||
<a
|
||||
className="App-link"
|
||||
href="https://reactjs.org"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Learn React!
|
||||
</a>
|
||||
</header>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Popup;
|
||||
17
src/pages/Popup/index.css
Normal file
17
src/pages/Popup/index.css
Normal file
@@ -0,0 +1,17 @@
|
||||
body {
|
||||
width: 300px;
|
||||
height: 260px;
|
||||
margin: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
||||
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
||||
sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
|
||||
position: relative;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
||||
monospace;
|
||||
}
|
||||
12
src/pages/Popup/index.html
Normal file
12
src/pages/Popup/index.html
Normal file
@@ -0,0 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>Popup</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app-container"></div>
|
||||
</body>
|
||||
</html>
|
||||
9
src/pages/Popup/index.jsx
Normal file
9
src/pages/Popup/index.jsx
Normal file
@@ -0,0 +1,9 @@
|
||||
import React from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
|
||||
import Popup from './Popup';
|
||||
import './index.css';
|
||||
|
||||
const container = document.getElementById('app-container');
|
||||
const root = createRoot(container); // createRoot(container!) if you use TypeScript
|
||||
root.render(<Popup />);
|
||||
20
tsconfig.json
Normal file
20
tsconfig.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"allowJs": false,
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"noEmit": false,
|
||||
"jsx": "react"
|
||||
},
|
||||
"include": ["src"],
|
||||
"exclude": ["build", "node_modules"]
|
||||
}
|
||||
27
utils/build.js
Executable file
27
utils/build.js
Executable file
@@ -0,0 +1,27 @@
|
||||
// Do this as the first thing so that any code reading it knows the right env.
|
||||
process.env.BABEL_ENV = 'production';
|
||||
process.env.NODE_ENV = 'production';
|
||||
process.env.ASSET_PATH = '/';
|
||||
|
||||
var webpack = require('webpack'),
|
||||
path = require('path'),
|
||||
fs = require('fs'),
|
||||
config = require('../webpack.config'),
|
||||
ZipPlugin = require('zip-webpack-plugin');
|
||||
|
||||
delete config.chromeExtensionBoilerplate;
|
||||
|
||||
config.mode = 'production';
|
||||
|
||||
var packageInfo = JSON.parse(fs.readFileSync('package.json', 'utf-8'));
|
||||
|
||||
config.plugins = (config.plugins || []).concat(
|
||||
new ZipPlugin({
|
||||
filename: `${packageInfo.name}-${packageInfo.version}.zip`,
|
||||
path: path.join(__dirname, '../', 'zip'),
|
||||
})
|
||||
);
|
||||
|
||||
webpack(config, function (err) {
|
||||
if (err) throw err;
|
||||
});
|
||||
5
utils/env.js
Executable file
5
utils/env.js
Executable file
@@ -0,0 +1,5 @@
|
||||
// tiny wrapper with default env vars
|
||||
module.exports = {
|
||||
NODE_ENV: process.env.NODE_ENV || 'development',
|
||||
PORT: process.env.PORT || 3000,
|
||||
};
|
||||
56
utils/webserver.js
Executable file
56
utils/webserver.js
Executable file
@@ -0,0 +1,56 @@
|
||||
// Do this as the first thing so that any code reading it knows the right env.
|
||||
process.env.BABEL_ENV = 'development';
|
||||
process.env.NODE_ENV = 'development';
|
||||
process.env.ASSET_PATH = '/';
|
||||
|
||||
var WebpackDevServer = require('webpack-dev-server'),
|
||||
webpack = require('webpack'),
|
||||
config = require('../webpack.config'),
|
||||
env = require('./env'),
|
||||
path = require('path');
|
||||
|
||||
var options = config.chromeExtensionBoilerplate || {};
|
||||
var excludeEntriesToHotReload = options.notHotReload || [];
|
||||
|
||||
for (var entryName in config.entry) {
|
||||
if (excludeEntriesToHotReload.indexOf(entryName) === -1) {
|
||||
config.entry[entryName] = [
|
||||
'webpack/hot/dev-server',
|
||||
`webpack-dev-server/client?hot=true&hostname=localhost&port=${env.PORT}`,
|
||||
].concat(config.entry[entryName]);
|
||||
}
|
||||
}
|
||||
|
||||
delete config.chromeExtensionBoilerplate;
|
||||
|
||||
var compiler = webpack(config);
|
||||
|
||||
var server = new WebpackDevServer(
|
||||
{
|
||||
https: false,
|
||||
hot: true,
|
||||
liveReload: false,
|
||||
client: {
|
||||
webSocketTransport: 'sockjs',
|
||||
},
|
||||
webSocketServer: 'sockjs',
|
||||
host: 'localhost',
|
||||
port: env.PORT,
|
||||
static: {
|
||||
directory: path.join(__dirname, '../build'),
|
||||
},
|
||||
devMiddleware: {
|
||||
publicPath: `http://localhost:${env.PORT}/`,
|
||||
writeToDisk: true,
|
||||
},
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
},
|
||||
allowedHosts: 'all',
|
||||
},
|
||||
compiler
|
||||
);
|
||||
|
||||
(async () => {
|
||||
await server.start();
|
||||
})();
|
||||
253
webpack.config.js
Normal file → Executable file
253
webpack.config.js
Normal file → Executable file
@@ -1,31 +1,236 @@
|
||||
const path = require('path');
|
||||
const CopyPlugin = require("copy-webpack-plugin");
|
||||
var webpack = require('webpack'),
|
||||
path = require('path'),
|
||||
fileSystem = require('fs-extra'),
|
||||
env = require('./utils/env'),
|
||||
CopyWebpackPlugin = require('copy-webpack-plugin'),
|
||||
HtmlWebpackPlugin = require('html-webpack-plugin'),
|
||||
TerserPlugin = require('terser-webpack-plugin');
|
||||
var { CleanWebpackPlugin } = require('clean-webpack-plugin');
|
||||
var ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
|
||||
var ReactRefreshTypeScript = require('react-refresh-typescript');
|
||||
|
||||
module.exports = {
|
||||
mode: 'development',
|
||||
const ASSET_PATH = process.env.ASSET_PATH || '/';
|
||||
|
||||
var alias = {};
|
||||
|
||||
// load the secrets
|
||||
var secretsPath = path.join(__dirname, 'secrets.' + env.NODE_ENV + '.js');
|
||||
|
||||
var fileExtensions = [
|
||||
'jpg',
|
||||
'jpeg',
|
||||
'png',
|
||||
'gif',
|
||||
'eot',
|
||||
'otf',
|
||||
'svg',
|
||||
'ttf',
|
||||
'woff',
|
||||
'woff2',
|
||||
];
|
||||
|
||||
if (fileSystem.existsSync(secretsPath)) {
|
||||
alias['secrets'] = secretsPath;
|
||||
}
|
||||
|
||||
const isDevelopment = process.env.NODE_ENV !== 'production';
|
||||
|
||||
var options = {
|
||||
mode: process.env.NODE_ENV || 'development',
|
||||
entry: {
|
||||
newtab: path.join(__dirname, 'src', 'pages', 'Newtab', 'index.jsx'),
|
||||
options: path.join(__dirname, 'src', 'pages', 'Options', 'index.jsx'),
|
||||
popup: path.join(__dirname, 'src', 'pages', 'Popup', 'index.jsx'),
|
||||
background: path.join(__dirname, 'src', 'pages', 'Background', 'index.js'),
|
||||
contentScript: path.join(__dirname, 'src', 'pages', 'Content', 'index.js'),
|
||||
devtools: path.join(__dirname, 'src', 'pages', 'Devtools', 'index.js'),
|
||||
panel: path.join(__dirname, 'src', 'pages', 'Panel', 'index.jsx'),
|
||||
},
|
||||
chromeExtensionBoilerplate: {
|
||||
notHotReload: ['background', 'contentScript', 'devtools'],
|
||||
},
|
||||
output: {
|
||||
filename: '[name].bundle.js',
|
||||
path: path.resolve(__dirname, 'build'),
|
||||
clean: true,
|
||||
publicPath: ASSET_PATH,
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
// look for .css or .scss files
|
||||
test: /\.(css|scss)$/,
|
||||
// in the `src` directory
|
||||
use: [
|
||||
{
|
||||
loader: 'style-loader',
|
||||
},
|
||||
{
|
||||
loader: 'css-loader',
|
||||
},
|
||||
{
|
||||
loader: 'sass-loader',
|
||||
options: {
|
||||
sourceMap: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
test: new RegExp('.(' + fileExtensions.join('|') + ')$'),
|
||||
type: 'asset/resource',
|
||||
exclude: /node_modules/,
|
||||
// loader: 'file-loader',
|
||||
// options: {
|
||||
// name: '[name].[ext]',
|
||||
// },
|
||||
},
|
||||
{
|
||||
test: /\.html$/,
|
||||
loader: 'html-loader',
|
||||
exclude: /node_modules/,
|
||||
},
|
||||
{
|
||||
test: /\.(ts|tsx)$/,
|
||||
exclude: /node_modules/,
|
||||
use: [
|
||||
{
|
||||
loader: require.resolve('ts-loader'),
|
||||
options: {
|
||||
getCustomTransformers: () => ({
|
||||
before: [isDevelopment && ReactRefreshTypeScript()].filter(
|
||||
Boolean
|
||||
),
|
||||
}),
|
||||
transpileOnly: isDevelopment,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.(js|jsx)$/,
|
||||
use: [
|
||||
{
|
||||
loader: 'source-map-loader',
|
||||
},
|
||||
{
|
||||
loader: require.resolve('babel-loader'),
|
||||
options: {
|
||||
plugins: [
|
||||
isDevelopment && require.resolve('react-refresh/babel'),
|
||||
].filter(Boolean),
|
||||
},
|
||||
},
|
||||
],
|
||||
exclude: /node_modules/,
|
||||
},
|
||||
],
|
||||
},
|
||||
resolve: {
|
||||
alias: alias,
|
||||
extensions: fileExtensions
|
||||
.map((extension) => '.' + extension)
|
||||
.concat(['.js', '.jsx', '.ts', '.tsx', '.css']),
|
||||
},
|
||||
plugins: [
|
||||
new CopyPlugin({
|
||||
isDevelopment && new ReactRefreshWebpackPlugin(),
|
||||
new CleanWebpackPlugin({ verbose: false }),
|
||||
new webpack.ProgressPlugin(),
|
||||
// expose and write the allowed env vars on the compiled bundle
|
||||
new webpack.EnvironmentPlugin(['NODE_ENV']),
|
||||
new CopyWebpackPlugin({
|
||||
patterns: [
|
||||
{ from: 'index.html' },
|
||||
{ from: 'pkg/', to: 'pkg/' },
|
||||
{
|
||||
from: 'src/manifest.json',
|
||||
to: path.join(__dirname, 'build'),
|
||||
force: true,
|
||||
transform: function (content, path) {
|
||||
// generates the manifest file using the package.json informations
|
||||
return Buffer.from(
|
||||
JSON.stringify({
|
||||
description: process.env.npm_package_description,
|
||||
version: process.env.npm_package_version,
|
||||
...JSON.parse(content.toString()),
|
||||
})
|
||||
);
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
],
|
||||
// FIXME: this is required to show which library causes
|
||||
// "Module not found: Error: Can't resolve 'env'"
|
||||
resolve: {
|
||||
fallback: {
|
||||
"env": false
|
||||
},
|
||||
new CopyWebpackPlugin({
|
||||
patterns: [
|
||||
{
|
||||
from: 'src/pages/Content/content.styles.css',
|
||||
to: path.join(__dirname, 'build'),
|
||||
force: true,
|
||||
},
|
||||
],
|
||||
}),
|
||||
new CopyWebpackPlugin({
|
||||
patterns: [
|
||||
{
|
||||
from: 'src/assets/img/icon-128.png',
|
||||
to: path.join(__dirname, 'build'),
|
||||
force: true,
|
||||
},
|
||||
],
|
||||
}),
|
||||
new CopyWebpackPlugin({
|
||||
patterns: [
|
||||
{
|
||||
from: 'src/assets/img/icon-34.png',
|
||||
to: path.join(__dirname, 'build'),
|
||||
force: true,
|
||||
},
|
||||
],
|
||||
}),
|
||||
new HtmlWebpackPlugin({
|
||||
template: path.join(__dirname, 'src', 'pages', 'Newtab', 'index.html'),
|
||||
filename: 'newtab.html',
|
||||
chunks: ['newtab'],
|
||||
cache: false,
|
||||
}),
|
||||
new HtmlWebpackPlugin({
|
||||
template: path.join(__dirname, 'src', 'pages', 'Options', 'index.html'),
|
||||
filename: 'options.html',
|
||||
chunks: ['options'],
|
||||
cache: false,
|
||||
}),
|
||||
new HtmlWebpackPlugin({
|
||||
template: path.join(__dirname, 'src', 'pages', 'Popup', 'index.html'),
|
||||
filename: 'popup.html',
|
||||
chunks: ['popup'],
|
||||
cache: false,
|
||||
}),
|
||||
new HtmlWebpackPlugin({
|
||||
template: path.join(__dirname, 'src', 'pages', 'Devtools', 'index.html'),
|
||||
filename: 'devtools.html',
|
||||
chunks: ['devtools'],
|
||||
cache: false,
|
||||
}),
|
||||
new HtmlWebpackPlugin({
|
||||
template: path.join(__dirname, 'src', 'pages', 'Panel', 'index.html'),
|
||||
filename: 'panel.html',
|
||||
chunks: ['panel'],
|
||||
cache: false,
|
||||
}),
|
||||
].filter(Boolean),
|
||||
infrastructureLogging: {
|
||||
level: 'info',
|
||||
},
|
||||
entry: {
|
||||
bootstrap: path.join(__dirname, 'bootstrap'),
|
||||
worker: path.join(__dirname, 'worker.js'),
|
||||
},
|
||||
devServer: {
|
||||
headers: {
|
||||
'Cross-Origin-Embedder-Policy': 'require-corp',
|
||||
'Cross-Origin-Opener-Policy': 'same-origin',
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (env.NODE_ENV === 'development') {
|
||||
options.devtool = 'cheap-module-source-map';
|
||||
} else {
|
||||
options.optimization = {
|
||||
minimize: true,
|
||||
minimizer: [
|
||||
new TerserPlugin({
|
||||
extractComments: false,
|
||||
}),
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = options;
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
import { WebSocketServer } from 'ws';
|
||||
|
||||
const wss = new WebSocketServer({ port: 5566 });
|
||||
|
||||
wss.on('connection', function connection(ws) {
|
||||
ws.on('message', function message(data) {
|
||||
console.log('received: %s', data);
|
||||
});
|
||||
|
||||
ws.send('something');
|
||||
});
|
||||
console.log("ws server started")
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"name": "ws-server",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"start": "node index.js"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"ws": "^8.13.0"
|
||||
},
|
||||
"type": "module"
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
ws@^8.13.0:
|
||||
version "8.13.0"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0"
|
||||
integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==
|
||||
Reference in New Issue
Block a user