25
loading...
This website collects cookies to deliver better user experience
alias npi='npm i -g'
alias npd='npm i -D'
alias npu='npm un'
alias npr='npm run'
alias ssz='source ~/.zshrc'
npx create-react-app --scripts-version react-browser-extension-scripts --template browser-extension <project name>
npm start
then, once it builds you can go to your browser and open the chrome://extensions
page. Once there you can click the "Developer mode" switch, click the "Load unpacked" button and select the dev
folder generated by CRA. eject
the project and this is an irreversible operation. And once you do, you need to maintain the configuration and keep it updated by yourself, so this isn't recommended.npd react-app-rewired
if you're using my alias from the previous section, otherwise:npm install react-app-rewired --save-dev
config-overrides.js
at the root of your project (i.e: at the same level as the node_modules and src folders) where we will put our custom configuration.scripts
section of your package.json to use react-app-rewired instead of the react-scripts package:/* in package.json */
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test",
"eject": "react-scripts eject"
}
./MyComponent
or ../../MyParentComponent
. VSCode has support for using aliases, so you can import your package with an alias, get intellisense and go to definition:import MyComponent from "@Components/MyComponent"
jsconfig.json
in the src
folder of your project, which will tell the TypeScript Language Server from VSCode to do some nice things for us:{
"compilerOptions": {
"baseUrl": ".",
"module": "commonJS",
"target": "es6",
"sourceMap": true,
"paths": {
"@Config/*": ["config/*"],
"@Components/*": ["components/*"],
"@Containers/*": ["containers/*"],
"@Handlers/*": ["handlers/*"],
"@Utils/*": ["utils/*"],
"@Style": ["style/style.js"]
}
},
"typeAcquisition": {
"include": ["chrome"]
},
"include": ["./**/*"],
"exclude": ["node_modules"]
}
compilerOptions
here, but have a brief description of the most important ones:baseUrl
indicates the base path used for the paths
property, the src folder in this casepaths
is an array of in which you will configure how aliases are resolved when importingtypeAcquisition
is required if you want intellisense for some packages, such as chrome apis in this caseinclude
and exclude
tells TypeScript which files are to be used for resolving and compilingconfig-overrides.js
to tell webpack about those aliases.const path = require("path");
module.exports = function override(config) {
config.resolve = {
...config.resolve,
alias: {
...config.alias,
"@Config": path.resolve(__dirname, "src/config"),
"@Components": path.resolve(__dirname, "src/components"),
"@Containers": path.resolve(__dirname, "src/containers"),
"@Utils": path.resolve(__dirname, "src/utils"),
"@Style$": path.resolve(__dirname, "src/style/style.js"),
},
};
return config;
};
webpack.config.js
used by react when compiling and running the app, and appending our custom aliases to the aliases collection in case any exists. Now you can save the file and run npm start
in the console and you can start using your aliases. import MyFileInsideTheFolder from "@MyAliasName/MyFileInsideTheFolder"
import Styles from "@Styles"
npx react-devtools
<script src="http://localhost:8097"></script>
public/manifest.json
and paste this line at the end:"content_security_policy": "script-src 'self' 'unsafe-eval' http://localhost:8097; object-src 'self'; connect-src ws://localhost:4000 ws://localhost:8097"
script-src
refers to the origin of the scripts to be used by the extension
self
tells to load scripts from the same originunsafe-eval
tells to allow code to be run by eval (this is used by webpack to generate the sourcemaps)http://localhost:8097
allow scripts coming from the React dev-toolsconnect-src
tells Chrome to allow some protocols (like websockets in this case) to connect to our app
http://localhost:8097
again, allow the React dev-tools to connect to our extensionws://localhost:4000
this is used by webpack for the hot reloadconfig-overrides.js
and add this line before returning the config:config.devtool = "eval-source-map";
.eslintrc.js
(it may be a json, js or yaml) at the root of your project to configure the rules and behavior of ESLint. npm install --save-dev eslint
npx eslint --init
rules
array with the desired options. In my case, I modified the no-unused-vars
to ignore discards (_):rules: {
"no-unused-vars": [
"warn",
{
vars: "all",
args: "after-used",
ignoreRestSiblings: false,
varsIgnorePattern: "_",
argsIgnorePattern: "_",
},
],
console.log()
during development to keep track of things like windows or tabs id, but I want them removed from the production script. customize-cra
package to allow the injection of plugins and loaderstransform-remove-console
babel plugin to remove all console.* calls from our codenpm install --save-dev customize-cra babel-plugin-transform-remove-console
config-overrides.js
file once again. The override
method from customize-cra receives a list of functions, so we need to change the signature like this:const path = require("path");
const { override, addBabelPlugin } = require("customize-cra");
module.exports = override(
);
transform-remove-console
plugin:const path = require("path");
const { override, addBabelPlugin } = require("customize-cra");
module.exports = override(
addBabelPlugin("transform-remove-console")
);
const path = require("path");
const { override, addBabelPlugin } = require("customize-cra");
module.exports = override(
addBabelPlugin("transform-remove-console"),
(config, env) => customOverride(config, env)
);
function customOverride(config, env) {
config.devtool = "eval-source-map";
config.resolve = {
...config.resolve,
alias: {
...config.alias,
"@Config": path.resolve(__dirname, "src/config"),
"@Components": path.resolve(__dirname, "src/components"),
"@Containers": path.resolve(__dirname, "src/containers"),
"@Handlers": path.resolve(__dirname, "src/handlers"),
"@Utils": path.resolve(__dirname, "src/utils"),
"@Style$": path.resolve(__dirname, "src/style/style.js"),
},
};
return config;
}
development
, so our final config-overrides.js
will look like this:const path = require("path");
const { override, addBabelPlugin } = require("customize-cra");
module.exports = override(
addBabelPlugin("transform-remove-console"),
(config, env) => customOverride(config, env)
);
function customOverride(config, env) {
config.devtool = "eval-source-map";
config.resolve = {
...config.resolve,
alias: {
...config.alias,
"@Config": path.resolve(__dirname, "src/config"),
"@Components": path.resolve(__dirname, "src/components"),
"@Containers": path.resolve(__dirname, "src/containers"),
"@Handlers": path.resolve(__dirname, "src/handlers"),
"@Utils": path.resolve(__dirname, "src/utils"),
"@Style$": path.resolve(__dirname, "src/style/style.js"),
},
};
if (env !== "development") {
config.devtool = false;
}
return config;
}