Skip to content

Commit

Permalink
Update cra-template for react 17
Browse files Browse the repository at this point in the history
  • Loading branch information
abillingsley committed Oct 29, 2020
1 parent 28ef8d6 commit 86d70b5
Show file tree
Hide file tree
Showing 21 changed files with 177 additions and 53 deletions.
2 changes: 1 addition & 1 deletion react/cra-template/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@developertown/cra-template",
"version": "0.0.12",
"version": "0.1.0",
"keywords": [
"react",
"create-react-app",
Expand Down
70 changes: 45 additions & 25 deletions react/cra-template/template.json
Original file line number Diff line number Diff line change
@@ -1,71 +1,91 @@
{
"package": {
"dependencies": {
"@babel/core": "^7.12.3",
"@material-ui/core": "^4.9.5",
"@material-ui/icons": "^4.9.1",
"@storybook/addon-a11y": "^6.0.21",
"@storybook/addon-essentials": "^6.0.21",
"@storybook/addon-knobs": "^6.0.21",
"@storybook/addon-actions": "^6.0.27",
"@storybook/addon-a11y": "^6.0.27",
"@storybook/addon-essentials": "^6.0.27",
"@storybook/addon-links": "^6.0.27",
"@storybook/addon-knobs": "^6.0.27",
"@storybook/node-logger": "^6.0.27",
"@storybook/preset-create-react-app": "^3.1.4",
"@storybook/react": "^6.0.21",
"@testing-library/jest-dom": "^5.1.1",
"@testing-library/react": "^11.0.4",
"@storybook/react": "^6.0.27",
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.1.0",
"@testing-library/cypress": "^7.0.1",
"@testing-library/react-hooks": "^3.2.1",
"@testing-library/user-event": "^12.1.5",
"@testing-library/user-event": "^12.1.10",
"@types/classnames": "^2.2.10",
"@types/jest": "^26.0.14",
"@types/jest": "^26.0.15",
"@types/jest-axe": "^3.2.1",
"@types/node": "^14.10.2",
"@types/react": "^16.9.0",
"@types/react-dom": "^16.9.0",
"@types/node": "^12.0.0",
"@types/react": "^16.9.53",
"@types/react-dom": "^16.9.8",
"@types/react-helmet": "^6.1.0",
"@types/react-router": "^5.1.4",
"@types/react-router-dom": "^5.1.3",
"@typescript-eslint/eslint-plugin": "^2.24.0",
"@typescript-eslint/parser": "^2.24.0",
"@typescript-eslint/eslint-plugin": "^4.6.0",
"@typescript-eslint/parser": "^4.6.0",
"babel-loader": "^8.1.0",
"classnames": "^2.2.6",
"cypress": "^5.2.0",
"dotenv-cli": "^4.0.0",
"eslint": "^6.8.0",
"eslint": "^7.12.1",
"eslint-config-prettier": "^6.10.0",
"eslint-config-react-app": "^5.2.0",
"eslint-config-react-app": "^6.0.0",
"eslint-plugin-cypress": "^2.10.3",
"eslint-plugin-flowtype": "^4.6.0",
"eslint-plugin-flowtype": "^5.2.0",
"eslint-plugin-import": "^2.20.1",
"eslint-plugin-jest": "^23.8.2",
"eslint-plugin-jest": "^24.1.0",
"eslint-plugin-jsx-a11y": "^6.2.3",
"eslint-plugin-prettier": "^3.1.2",
"eslint-plugin-react": "^7.19.0",
"eslint-plugin-react-hooks": "^2.5.0",
"eslint-plugin-react-hooks": "^4.2.0",
"eslint-plugin-testing-library": "^3.0.4",
"http-proxy-middleware": "^1.0.3",
"i18next": "^19.5.0",
"i18next-browser-languagedetector": "^6.0.1",
"i18next-xhr-backend": "^3.2.2",
"jest-axe": "^4.0.0",
"jest-junit": "^11.1.0",
"jest-junit": "^12.0.0",
"jest-sonar-reporter": "^2.0.0",
"prettier": "^2.0.2",
"react-app-polyfill": "^1.0.6",
"react-app-polyfill": "^2.0.0",
"react-error-boundary": "^3.0.2",
"react-helmet": "^6.0.0",
"react-i18next": "^11.7.0",
"react-is": "^17.0.1",
"react-router": "^5.1.2",
"react-router-dom": "^5.1.2",
"react-test-renderer": "^16.13.1",
"react-test-renderer": "^17.0.1",
"static-route-paths": "^0.2.2",
"source-map-explorer": "^2.4.0",
"storybook-addon-i18n": "^5.1.13",
"storybook-addon-material-ui": "^0.9.0-alpha.21",
"typescript": "~3.8.3",
"typescript": "^4.0.3",
"typescript-fsa": "^3.0.0",
"typescript-fsa-reducers": "^1.2.1"
"typescript-fsa-reducers": "^1.2.1",
"web-vitals": "^0.2.4",
"workbox-background-sync": "^5.1.3",
"workbox-broadcast-update": "^5.1.3",
"workbox-cacheable-response": "^5.1.3",
"workbox-core": "^5.1.3",
"workbox-expiration": "^5.1.3",
"workbox-google-analytics": "^5.1.3",
"workbox-navigation-preload": "^5.1.3",
"workbox-precaching": "^5.1.3",
"workbox-range-requests": "^5.1.3",
"workbox-routing": "^5.1.3",
"workbox-strategies": "^5.1.3",
"workbox-streams": "^5.1.3"
},
"scripts": {
"prestart": "chmod +x ./env.sh && dotenv -e .env.development.local -e .env.development -e .env.local -e .env ./env.sh ./public/env.js",
"clean": "rm -rf ./build",
"analyze": "source-map-explorer 'build/static/js/*.js'",
"storybook": "start-storybook -s ./public",
"storybook": "start-storybook -p 6006 -s public",
"test:e2e": "cypress open",
"test:watch": "npm run test -- --watchAll",
"test:coverage": "npm run test -- --watchAll=false --coverage --reporters=default --reporters=jest-junit --testResultsProcessor=jest-sonar-reporter",
Expand All @@ -75,7 +95,7 @@
"jest": {
"collectCoverageFrom": [
"src/**/*.{js,jsx,ts,tsx}",
"!src/{setupProxy,serviceWorker}.{js,jsx,ts,tsx}",
"!src/{setupProxy,service-worker,serviceWorkerRegistration,reportWebVitals}.{js,jsx,ts,tsx}",
"!src/**/*.story.{js,jsx,ts,tsx}"
],
"coverageReporters": ["json", "lcov", "text", "clover", "cobertura"]
Expand Down
6 changes: 3 additions & 3 deletions react/cra-template/template/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"extends": [
"react-app",
"react-app/jest",
"plugin:@typescript-eslint/recommended",
"plugin:jsx-a11y/recommended",
"plugin:jest/recommended",
Expand All @@ -16,11 +17,10 @@
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/no-use-before-define": "off",
"@typescript-eslint/no-unused-vars": "warn",
"@typescript-eslint/explicit-module-boundary-types": "off",
"no-console": "warn",
"import/no-anonymous-default-export": "off",
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "warn"
},
"env": {
"cypress/globals": true
}
}
8 changes: 1 addition & 7 deletions react/cra-template/template/.storybook/preview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,4 @@ export const parameters = {
},
};

export const decorators = [
muiTheme([theme]),
withCssBaseline,
withKnobs,
withA11y,
withI18n
];
export const decorators = [muiTheme([theme]), withCssBaseline, withKnobs, withA11y, withI18n];
4 changes: 2 additions & 2 deletions react/cra-template/template/azure-pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ pool:
vmImage: "ubuntu-16.04"

stages:
- template: azp-templates/build.yml
# - template: azp-templates/deploy-<REPLACE-WITH-STRATEGY>.yml
- template: .azure-pipelines/build.yml
# - template: .azure-pipelines/deploy-<REPLACE-WITH-STRATEGY>.yml
# parameters:
# condition: "or(eq(variables['build.sourceBranch'], 'refs/heads/develop'), eq(variables['build.sourceBranch'], 'refs/heads/master'))"
# environment: 'Test'
5 changes: 4 additions & 1 deletion react/cra-template/template/cypress/integration/app_spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
/* eslint-disable jest/expect-expect */
/// <reference types="cypress" />

describe("App", () => {
it("successfully loads", () => {
cy.visit("/");
cy.contains("Learn React");
cy.findByText("Learn React");
});
});
6 changes: 5 additions & 1 deletion react/cra-template/template/cypress/plugins/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/// <reference types="cypress" />
// ***********************************************************
// This example plugins/index.js can be used to load plugins
//
Expand All @@ -11,7 +12,10 @@
// This function is called when a project is opened or re-opened (e.g. due to
// the project's config changing)

/**
* @type {Cypress.PluginConfig}
*/
module.exports = (on, config) => {
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
}
};
3 changes: 2 additions & 1 deletion react/cra-template/template/cypress/support/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,6 @@
// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
//
//
// -- This is will overwrite an existing command --
// -- This will overwrite an existing command --
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
import "@testing-library/cypress/add-commands";
1 change: 0 additions & 1 deletion react/cra-template/template/cypress/support/index.d.ts

This file was deleted.

4 changes: 2 additions & 2 deletions react/cra-template/template/public/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
"sizes": "192x192"
},
{
"src": "android-chrome-384x384.png",
"sizes": "384x384",
"src": "android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
Expand Down
1 change: 1 addition & 0 deletions react/cra-template/template/src/__mocks__/react-i18next.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// eslint-disable-next-line no-use-before-define
import React from "react";
import * as reactI18next from "react-i18next";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import React from "react";
import { render } from "@testing-library/react";
import { render, screen } from "@testing-library/react";
import { axe } from "jest-axe";
import App from "../app";

test("renders learn react link", () => {
const { getByText } = render(<App />);
const linkElement = getByText(/learn react/i);
render(<App />);
const linkElement = screen.getByText(/learn react/i);
expect(linkElement).toBeInTheDocument();
});

Expand Down
1 change: 1 addition & 0 deletions react/cra-template/template/src/components/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ const useStyles = makeStyles((theme: Theme) => ({
}));

type CustomWindow = Window & {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
env?: any;
};

Expand Down
12 changes: 9 additions & 3 deletions react/cra-template/template/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import { ThemeProvider } from "@material-ui/core/styles";
import { theme } from "./styles";
import i18n from "./i18n";
import App from "./ui";
import * as serviceWorker from "./serviceWorker";
import * as serviceWorkerRegistration from "./serviceWorkerRegistration";
import reportWebVitals from "./reportWebVitals";

const Loading: React.FC = () => {
return <div>Loading...</div>;
Expand All @@ -32,7 +33,12 @@ const Root: React.FC = () => {

ReactDOM.render(<Root />, document.getElementById("root"));

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();
// Learn more about service workers: https://cra.link/PWA
serviceWorkerRegistration.unregister();
15 changes: 15 additions & 0 deletions react/cra-template/template/src/reportWebVitals.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { ReportHandler } from "web-vitals";

const reportWebVitals = (onPerfEntry?: ReportHandler) => {
if (onPerfEntry && onPerfEntry instanceof Function) {
import("web-vitals").then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
getCLS(onPerfEntry);
getFID(onPerfEntry);
getFCP(onPerfEntry);
getLCP(onPerfEntry);
getTTFB(onPerfEntry);
});
}
};

export default reportWebVitals;
80 changes: 80 additions & 0 deletions react/cra-template/template/src/service-worker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/// <reference lib="webworker" />
/* eslint-disable no-restricted-globals */

// This service worker can be customized!
// See https://developers.google.com/web/tools/workbox/modules
// for the list of available Workbox modules, or add any other
// code you'd like.
// You can also remove this file if you'd prefer not to use a
// service worker, and the Workbox build step will be skipped.

import { clientsClaim } from "workbox-core";
import { ExpirationPlugin } from "workbox-expiration";
import { precacheAndRoute, createHandlerBoundToURL } from "workbox-precaching";
import { registerRoute } from "workbox-routing";
import { StaleWhileRevalidate } from "workbox-strategies";

declare const self: ServiceWorkerGlobalScope;

clientsClaim();

// Precache all of the assets generated by your build process.
// Their URLs are injected into the manifest variable below.
// This variable must be present somewhere in your service worker file,
// even if you decide not to use precaching. See https://cra.link/PWA
precacheAndRoute(self.__WB_MANIFEST);

// Set up App Shell-style routing, so that all navigation requests
// are fulfilled with your index.html shell. Learn more at
// https://developers.google.com/web/fundamentals/architecture/app-shell
const fileExtensionRegexp = new RegExp("/[^/?]+\\.[^/]+$");
registerRoute(
// Return false to exempt requests from being fulfilled by index.html.
({ request, url }: { request: Request; url: URL }) => {
// If this isn't a navigation, skip.
if (request.mode !== "navigate") {
return false;
}

// If this is a URL that starts with /_, skip.
if (url.pathname.startsWith("/_")) {
return false;
}

// If this looks like a URL for a resource, because it contains
// a file extension, skip.
if (url.pathname.match(fileExtensionRegexp)) {
return false;
}

// Return true to signal that we want to use the handler.
return true;
},
createHandlerBoundToURL(process.env.PUBLIC_URL + "/index.html"),
);

// An example runtime caching route for requests that aren't handled by the
// precache, in this case same-origin .png requests like those from in public/
registerRoute(
// Add in any other file extensions or routing criteria as needed.
({ url }) => url.origin === self.location.origin && url.pathname.endsWith(".png"),
// Customize this strategy as needed, e.g., by changing to CacheFirst.
new StaleWhileRevalidate({
cacheName: "images",
plugins: [
// Ensure that once this runtime cache reaches a maximum size the
// least-recently used images are removed.
new ExpirationPlugin({ maxEntries: 50 }),
],
}),
);

// This allows the web app to trigger skipWaiting via
// registration.waiting.postMessage({type: 'SKIP_WAITING'})
self.addEventListener("message", (event) => {
if (event.data && event.data.type === "SKIP_WAITING") {
self.skipWaiting();
}
});

// Any other custom service worker logic can go here.
Loading

0 comments on commit 86d70b5

Please sign in to comment.