Service workers : Caching
This commit is contained in:
parent
cad7c70f61
commit
f57cf9d903
2
app/client/.gitignore
vendored
2
app/client/.gitignore
vendored
|
|
@ -31,3 +31,5 @@ yarn-error.log*
|
|||
cypress/videos
|
||||
cypress/screenshots
|
||||
results/
|
||||
|
||||
/docker/*.pem
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
const SentryWebpackPlugin = require("@sentry/webpack-plugin");
|
||||
const merge = require("webpack-merge");
|
||||
const common = require("./craco.common.config.js");
|
||||
const WorkboxPlugin = require("workbox-webpack-plugin");
|
||||
|
||||
const env = process.env.REACT_APP_ENVIRONMENT;
|
||||
|
||||
|
|
@ -16,6 +17,14 @@ if (env === "PRODUCTION" || env === "STAGING") {
|
|||
}),
|
||||
);
|
||||
}
|
||||
plugins.push(
|
||||
new WorkboxPlugin.InjectManifest({
|
||||
swSrc: "./src/serviceWorker.js",
|
||||
mode: "development",
|
||||
swDest: "./pageService.js",
|
||||
maximumFileSizeToCacheInBytes: 4 * 1024 * 1024,
|
||||
}),
|
||||
);
|
||||
|
||||
module.exports = merge(common, {
|
||||
webpack: {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ const modalWidgetPage = require("../locators/ModalWidget.json");
|
|||
const widgetsPage = require("../locators/Widgets.json");
|
||||
|
||||
Cypress.Commands.add("LogintoApp", (uname, pword) => {
|
||||
cy.visit("/");
|
||||
cy.visit("/user/login");
|
||||
cy.get(loginPage.username).should("be.visible");
|
||||
cy.get(loginPage.username).type(uname);
|
||||
cy.get(loginPage.password).type(pword);
|
||||
|
|
|
|||
63
app/client/docker/nginx-linux.conf
Normal file
63
app/client/docker/nginx-linux.conf
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
server {
|
||||
listen 80;
|
||||
server_name dev.appsmith.com;
|
||||
client_max_body_size 10m;
|
||||
|
||||
gzip on;
|
||||
gzip_proxied any;
|
||||
proxy_ssl_server_name on;
|
||||
# sub_filter_once off;
|
||||
location / {
|
||||
#proxy_set_header Host $host;
|
||||
#proxy_set_header X-Real-IP $remote_addr;
|
||||
# sub_filter ___BASE_URL___ http://$host;
|
||||
proxy_pass http://localhost:3000;
|
||||
}
|
||||
|
||||
location /api {
|
||||
# proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_pass https://release-api.appsmith.com;
|
||||
}
|
||||
|
||||
location /oauth2 {
|
||||
# proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_pass https://release-api.appsmith.com;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name dev.appsmith.com;
|
||||
|
||||
ssl_certificate /etc/certificate/dev.appsmith.com.pem;
|
||||
ssl_certificate_key /etc/certificate/dev.appsmith.com-key.pem;
|
||||
|
||||
# include /etc/letsencrypt/options-ssl-nginx.conf;
|
||||
# ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
|
||||
gzip on;
|
||||
|
||||
proxy_ssl_server_name on;
|
||||
# sub_filter_once off;
|
||||
location / {
|
||||
#proxy_set_header Host $host;
|
||||
#proxy_set_header X-Real-IP $remote_addr;
|
||||
# sub_filter ___BASE_URL___ http://$host;
|
||||
proxy_pass http://localhost:3000;
|
||||
}
|
||||
|
||||
location /api {
|
||||
# proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_pass https://release-api.appsmith.com;
|
||||
}
|
||||
|
||||
location /oauth2 {
|
||||
# proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_pass https://release-api.appsmith.com;
|
||||
}
|
||||
}
|
||||
|
||||
62
app/client/docker/nginx-mac.conf
Normal file
62
app/client/docker/nginx-mac.conf
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
server {
|
||||
listen 80;
|
||||
server_name dev.appsmith.com;
|
||||
client_max_body_size 10m;
|
||||
|
||||
gzip on;
|
||||
gzip_proxied any;
|
||||
proxy_ssl_server_name on;
|
||||
# sub_filter_once off;
|
||||
location / {
|
||||
#proxy_set_header Host $host;
|
||||
#proxy_set_header X-Real-IP $remote_addr;
|
||||
# sub_filter ___BASE_URL___ http://$host;
|
||||
proxy_pass http://host.docker.internal:3000;
|
||||
}
|
||||
|
||||
location /api {
|
||||
# proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_pass https://release-api.appsmith.com;
|
||||
}
|
||||
|
||||
location /oauth2 {
|
||||
# proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_pass https://release-api.appsmith.com;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name dev.appsmith.com;
|
||||
|
||||
ssl_certificate /etc/certificate/dev.appsmith.com.pem;
|
||||
ssl_certificate_key /etc/certificate/dev.appsmith.com-key.pem;
|
||||
|
||||
# include /etc/letsencrypt/options-ssl-nginx.conf;
|
||||
# ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
|
||||
gzip on;
|
||||
|
||||
proxy_ssl_server_name on;
|
||||
# sub_filter_once off;
|
||||
location / {
|
||||
#proxy_set_header Host $host;
|
||||
#proxy_set_header X-Real-IP $remote_addr;
|
||||
# sub_filter ___BASE_URL___ http://$host;
|
||||
proxy_pass http://host.docker.internal:3000;
|
||||
}
|
||||
|
||||
location /api {
|
||||
# proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_pass https://release-api.appsmith.com;
|
||||
}
|
||||
|
||||
location /oauth2 {
|
||||
# proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_pass https://release-api.appsmith.com;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
server {
|
||||
listen 80;
|
||||
server_name localhost;
|
||||
gzip on;
|
||||
|
||||
#charset koi8-r;
|
||||
#access_log /var/log/nginx/host.access.log main;
|
||||
root /var/www/appsmith;
|
||||
index index.html index.htm;
|
||||
|
||||
location / {
|
||||
try_files $uri /index.html =404;
|
||||
}
|
||||
|
||||
#error_page 404 /404.html;
|
||||
|
||||
# redirect server error pages to the static page /50x.html
|
||||
#
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
location = /50x.html {
|
||||
root /var/www/appsmith;
|
||||
}
|
||||
|
||||
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
|
||||
#
|
||||
#location ~ \.php$ {
|
||||
# proxy_pass http://127.0.0.1;
|
||||
#}
|
||||
|
||||
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
|
||||
#
|
||||
#location ~ \.php$ {
|
||||
# root html;
|
||||
# fastcgi_pass 127.0.0.1:9000;
|
||||
# fastcgi_index index.php;
|
||||
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
|
||||
# include fastcgi_params;
|
||||
#}
|
||||
|
||||
# deny access to .htaccess files, if Apache's document root
|
||||
# concurs with nginx's one
|
||||
#
|
||||
#location ~ /\.ht {
|
||||
# deny all;
|
||||
#}
|
||||
}
|
||||
|
|
@ -167,8 +167,9 @@
|
|||
"redux-devtools-extension": "^2.13.8",
|
||||
"source-map-explorer": "^2.4.2",
|
||||
"storybook-addon-designs": "^5.1.1",
|
||||
"ts-jest": "^24.3.0",
|
||||
"webpack-merge": "^4.2.2"
|
||||
"webpack-merge": "^4.2.2",
|
||||
"workbox-webpack-plugin": "^5.1.2",
|
||||
"ts-jest": "^24.3.0"
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
|
|
|
|||
|
|
@ -2,18 +2,49 @@
|
|||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<script rel="prefetch" type="text/javascript" src="/shims/realms-shim.umd.min.js"></script>
|
||||
<meta charset="utf-8" />
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
|
||||
<link href="https://fonts.googleapis.com/css?family=DM+Sans:400,500,700&display=swap" rel="stylesheet" />
|
||||
<title>Appsmith</title>
|
||||
<style>
|
||||
#loader {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
height: 4px;
|
||||
background:#D36500;
|
||||
transition: all ease-in 0.3s;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="loader" style="width: 30vw;"></div>
|
||||
<div id="root"></div>
|
||||
<script type="text/javascript">
|
||||
window.BASE_URL = "___BASE_URL___";
|
||||
window.addEventListener("DOMContentLoaded", (event) => {
|
||||
document.getElementById("loader").style.width = "50vw";
|
||||
});
|
||||
window.addEventListener("load", (event) => {
|
||||
document.getElementById("loader").style.width = "100vw";
|
||||
setTimeout(() => {
|
||||
document.getElementById("loader").style.opacity = 0;
|
||||
});
|
||||
});
|
||||
const registerPageServiceWorker = () => {
|
||||
if ("serviceWorker" in navigator) {
|
||||
window.addEventListener("load", function () {
|
||||
navigator.serviceWorker.register("/pageService.js").catch(error => {
|
||||
console.log("Service Worker Registration failed: " + error);
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
registerPageServiceWorker();
|
||||
|
||||
</script>
|
||||
<script rel="prefetch" type="text/javascript" src="/shims/realms-shim.umd.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
</html>
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
"name": "Appsmith Client Web UI",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
"src": "favicon-orange.ico",
|
||||
"sizes": "64x64 32x32 24x24 16x16",
|
||||
"type": "image/x-icon"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,9 @@
|
|||
import React from "react";
|
||||
import { Redirect } from "react-router-dom";
|
||||
import { useSelector } from "store";
|
||||
import { APPLICATIONS_URL } from "constants/routes";
|
||||
|
||||
export const App = () => {
|
||||
const currentUser = useSelector(state => state.ui.users.current);
|
||||
return currentUser ? <Redirect to={APPLICATIONS_URL} /> : null;
|
||||
return <Redirect to={APPLICATIONS_URL} />;
|
||||
};
|
||||
|
||||
export default App;
|
||||
|
|
|
|||
|
|
@ -58,13 +58,15 @@ axiosInstance.interceptors.response.use(
|
|||
// console.log(error.response.status);
|
||||
// console.log(error.response.headers);
|
||||
if (error.response.status === 401) {
|
||||
setRouteBeforeLogin(window.location.pathname);
|
||||
history.push(AUTH_LOGIN_URL);
|
||||
return Promise.reject({
|
||||
code: 401,
|
||||
message: "Unauthorized. Redirecting to login page...",
|
||||
show: false,
|
||||
});
|
||||
if (!/^\/user\/\w+/.test(window.location.pathname)) {
|
||||
setRouteBeforeLogin(window.location.pathname);
|
||||
history.push(AUTH_LOGIN_URL);
|
||||
return Promise.reject({
|
||||
code: 401,
|
||||
message: "Unauthorized. Redirecting to login page...",
|
||||
show: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
if (error.response.data.responseMeta) {
|
||||
return Promise.resolve(error.response.data);
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ export interface FetchPageRequest {
|
|||
|
||||
export interface FetchPublishedPageRequest {
|
||||
pageId: string;
|
||||
bustCache?: boolean;
|
||||
}
|
||||
|
||||
export interface SavePageRequest {
|
||||
|
|
@ -92,8 +93,9 @@ class PageApi extends Api {
|
|||
return `v1/layouts/${layoutId}/pages/${pageId}`;
|
||||
};
|
||||
|
||||
static getPublishedPageURL = (pageId: string) => {
|
||||
return `v1/pages/${pageId}/view`;
|
||||
static getPublishedPageURL = (pageId: string, bustCache?: boolean) => {
|
||||
const url = `v1/pages/${pageId}/view`;
|
||||
return !!bustCache ? url + "?v=" + +new Date() : url;
|
||||
};
|
||||
|
||||
static updatePageUrl = (pageId: string) => `${PageApi.url}/${pageId}`;
|
||||
|
|
@ -120,7 +122,9 @@ class PageApi extends Api {
|
|||
static fetchPublishedPage(
|
||||
pageRequest: FetchPublishedPageRequest,
|
||||
): AxiosPromise<FetchPublishedPageResponse> {
|
||||
return Api.get(PageApi.getPublishedPageURL(pageRequest.pageId));
|
||||
return Api.get(
|
||||
PageApi.getPublishedPageURL(pageRequest.pageId, pageRequest.bustCache),
|
||||
);
|
||||
}
|
||||
|
||||
static createPage(
|
||||
|
|
|
|||
|
|
@ -198,6 +198,7 @@ export const ReduxActionTypes: { [key: string]: string } = {
|
|||
CLEAR_PROVIDERS: "CLEAR_PROVIDERS",
|
||||
BATCHED_UPDATE: "BATCHED_UPDATE",
|
||||
EXECUTE_BATCH: "EXECUTE_BATCH",
|
||||
FETCH_ALL_PUBLISHED_PAGES: "FETCH_ALL_PUBLISHED_PAGES",
|
||||
CREATE_NEW_API_ACTION: "CREATE_NEW_API_ACTION",
|
||||
SET_CURRENT_CATEGORY: "SET_CURRENT_CATEGORY",
|
||||
SET_LAST_USED_EDITOR_PAGE: "SET_LAST_USED_EDITOR_PAGE",
|
||||
|
|
|
|||
|
|
@ -42,11 +42,6 @@ div.bp3-popover-arrow {
|
|||
cursor: default !important;
|
||||
}
|
||||
|
||||
.pace-inactive {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
.display-none {
|
||||
display: none;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import "./index.css";
|
|||
import { Router, Switch, Redirect } from "react-router-dom";
|
||||
import history from "./utils/history";
|
||||
import { ThemeProvider, theme } from "constants/DefaultTheme";
|
||||
|
||||
import { appInitializer } from "utils/AppsmithUtils";
|
||||
import AppRoute from "./pages/common/AppRoute";
|
||||
import { Slide, ToastContainer } from "react-toastify";
|
||||
|
|
|
|||
|
|
@ -29,14 +29,14 @@ type AppViewerPageContainerProps = {
|
|||
isFetchingPage: boolean;
|
||||
widgets?: ContainerWidgetProps<WidgetProps>;
|
||||
currentPageName?: string;
|
||||
fetchPage: (pageId: string) => void;
|
||||
fetchPage: (pageId: string, bustCache?: boolean) => void;
|
||||
} & RouteComponentProps<AppViewerRouteParams>;
|
||||
|
||||
class AppViewerPageContainer extends Component<AppViewerPageContainerProps> {
|
||||
componentDidMount() {
|
||||
const { pageId } = this.props.match.params;
|
||||
if (pageId) {
|
||||
this.props.fetchPage(pageId);
|
||||
this.props.fetchPage(pageId, true);
|
||||
}
|
||||
}
|
||||
componentDidUpdate(previously: AppViewerPageContainerProps) {
|
||||
|
|
@ -99,11 +99,12 @@ const mapStateToProps = (state: AppState) => ({
|
|||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch: any) => ({
|
||||
fetchPage: (pageId: string) =>
|
||||
fetchPage: (pageId: string, bustCache = false) =>
|
||||
dispatch({
|
||||
type: ReduxActionTypes.FETCH_PUBLISHED_PAGE_INIT,
|
||||
payload: {
|
||||
pageId,
|
||||
bustCache,
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ const ApplicationImage = styled.div`
|
|||
}
|
||||
`;
|
||||
|
||||
const Control = styled.button<{ fixed?: boolean }>`
|
||||
const Control = styled.div<{ fixed?: boolean }>`
|
||||
outline: none;
|
||||
background: none;
|
||||
border: none;
|
||||
|
|
|
|||
|
|
@ -1,22 +1,12 @@
|
|||
import React, { useEffect } from "react";
|
||||
import { Route } from "react-router-dom";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { useSelector } from "store";
|
||||
import { hasAuthExpired } from "utils/storage";
|
||||
import { User } from "constants/userConstants";
|
||||
import { setCurrentUserDetails } from "actions/userActions";
|
||||
import {
|
||||
useShowPropertyPane,
|
||||
useWidgetSelection,
|
||||
} from "utils/hooks/dragResizeHooks";
|
||||
import AnalyticsUtil from "utils/AnalyticsUtil";
|
||||
export const checkAuth = (dispatch: any, currentUser?: User) => {
|
||||
return hasAuthExpired().then(hasExpired => {
|
||||
if (!currentUser || hasExpired) {
|
||||
dispatch(setCurrentUserDetails());
|
||||
}
|
||||
});
|
||||
};
|
||||
import { setCurrentUserDetails } from "actions/userActions";
|
||||
|
||||
export const WrappedComponent = (props: any) => {
|
||||
const showPropertyPane = useShowPropertyPane();
|
||||
|
|
@ -26,10 +16,7 @@ export const WrappedComponent = (props: any) => {
|
|||
selectWidget(undefined);
|
||||
focusWidget(undefined);
|
||||
|
||||
const dispatch = useDispatch();
|
||||
const currentUser = useSelector(state => state.ui.users.current);
|
||||
checkAuth(dispatch, currentUser);
|
||||
return currentUser || !props.protected ? props.children : null;
|
||||
return props.children;
|
||||
};
|
||||
|
||||
const AppRoute = ({
|
||||
|
|
@ -44,6 +31,13 @@ const AppRoute = ({
|
|||
name: string;
|
||||
location?: any;
|
||||
}) => {
|
||||
const dispatch = useDispatch();
|
||||
useEffect(() => {
|
||||
if (!/^\/user\/\w+/.test(rest.location.pathname)) {
|
||||
dispatch(setCurrentUserDetails());
|
||||
}
|
||||
}, [rest.name, rest.location.pathname, dispatch]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!rest.logDisable) {
|
||||
AnalyticsUtil.logEvent("NAVIGATE_EDITOR", {
|
||||
|
|
|
|||
|
|
@ -66,6 +66,10 @@ export function* initializeAppViewerSaga(
|
|||
take(ReduxActionTypes.FETCH_PAGE_LIST_SUCCESS),
|
||||
]);
|
||||
|
||||
yield put({
|
||||
type: ReduxActionTypes.FETCH_ALL_PUBLISHED_PAGES,
|
||||
});
|
||||
|
||||
yield put({
|
||||
type: ReduxActionTypes.INITIALIZE_PAGE_VIEWER_SUCCESS,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ import history from "utils/history";
|
|||
import { PAGE_LIST_EDITOR_URL } from "constants/routes";
|
||||
|
||||
import { extractCurrentDSL } from "utils/WidgetPropsUtils";
|
||||
import { getEditorConfigs, getWidgets } from "./selectors";
|
||||
import { getEditorConfigs, getWidgets, getAllPageIds } from "./selectors";
|
||||
import { validateResponse } from "./ErrorSagas";
|
||||
import { executePageLoadActions } from "actions/widgetActions";
|
||||
import { ApiResponse } from "api/ApiResponses";
|
||||
|
|
@ -151,12 +151,13 @@ export function* fetchPageSaga(
|
|||
}
|
||||
|
||||
export function* fetchPublishedPageSaga(
|
||||
pageRequestAction: ReduxAction<{ pageId: string }>,
|
||||
pageRequestAction: ReduxAction<{ pageId: string; bustCache: boolean }>,
|
||||
) {
|
||||
try {
|
||||
const { pageId } = pageRequestAction.payload;
|
||||
const { pageId, bustCache } = pageRequestAction.payload;
|
||||
const request: FetchPublishedPageRequest = {
|
||||
pageId,
|
||||
bustCache,
|
||||
};
|
||||
const response: FetchPublishedPageResponse = yield call(
|
||||
PageApi.fetchPublishedPage,
|
||||
|
|
@ -189,6 +190,19 @@ export function* fetchPublishedPageSaga(
|
|||
}
|
||||
}
|
||||
|
||||
export function* fetchAllPublishedPagesSaga() {
|
||||
try {
|
||||
const pageIds = yield select(getAllPageIds);
|
||||
yield all(
|
||||
pageIds.map((pageId: string) => {
|
||||
return call(PageApi.fetchPublishedPage, { pageId });
|
||||
}),
|
||||
);
|
||||
} catch (error) {
|
||||
console.log({ error });
|
||||
}
|
||||
}
|
||||
|
||||
function* savePageSaga() {
|
||||
const widgets = yield select(getWidgets);
|
||||
const editorConfigs = yield select(getEditorConfigs) as any;
|
||||
|
|
@ -401,5 +415,9 @@ export default function* pageSagas() {
|
|||
takeLatest(ReduxActionTypes.DELETE_PAGE_INIT, deletePageSaga),
|
||||
debounce(500, ReduxActionTypes.SAVE_PAGE_INIT, savePageSaga),
|
||||
takeLatest(ReduxActionTypes.UPDATE_WIDGET_NAME_INIT, updateWidgetNameSaga),
|
||||
takeLatest(
|
||||
ReduxActionTypes.FETCH_ALL_PUBLISHED_PAGES,
|
||||
fetchAllPublishedPagesSaga,
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -99,6 +99,10 @@ export const getWidgetByName = (
|
|||
);
|
||||
};
|
||||
|
||||
export const getAllPageIds = (state: AppState) => {
|
||||
return state.entities.pageList.pages.map(page => page.pageId);
|
||||
};
|
||||
|
||||
export const getPluginIdOfPackageName = (
|
||||
state: AppState,
|
||||
name: string,
|
||||
|
|
|
|||
188
app/client/src/serviceWorker.js
Executable file → Normal file
188
app/client/src/serviceWorker.js
Executable file → Normal file
|
|
@ -1,135 +1,61 @@
|
|||
// This optional code is used to register a service worker.
|
||||
// register() is not called by default.
|
||||
import { precacheAndRoute } from "workbox-precaching";
|
||||
import { clientsClaim, setCacheNameDetails, skipWaiting } from "workbox-core";
|
||||
import { registerRoute } from "workbox-routing";
|
||||
import {
|
||||
CacheFirst,
|
||||
NetworkOnly,
|
||||
StaleWhileRevalidate,
|
||||
} from "workbox-strategies";
|
||||
import { ExpirationPlugin } from "workbox-expiration";
|
||||
|
||||
// This lets the app load faster on subsequent visits in production, and gives
|
||||
// it offline capabilities. However, it also means that developers (and users)
|
||||
// will only see deployed updates on subsequent visits to a page, after all the
|
||||
// existing tabs open on the page have been closed, since previously cached
|
||||
// resources are updated in the background.
|
||||
setCacheNameDetails({
|
||||
prefix: "appsmith",
|
||||
suffix: undefined,
|
||||
precache: "precache-v1",
|
||||
runtime: "runtime",
|
||||
googleAnalytics: "appsmith-ga",
|
||||
});
|
||||
|
||||
// To learn more about the benefits of this model and instructions on how to
|
||||
// opt-in, read http://bit.ly/CRA-PWA
|
||||
const regexMap = {
|
||||
appViewPage: new RegExp(/api\/v1\/pages\/\w+\/view$/),
|
||||
static3PAssets: new RegExp(
|
||||
/(tiny.cloud|googleapis|gstatic|cloudfront).*.(js|css|woff2)/,
|
||||
),
|
||||
shims: new RegExp(/shims\/.*.js/),
|
||||
profile: new RegExp(/v1\/(users\/profile|organizations)/),
|
||||
providers: new RegExp(/v1\/marketplace\/(providers|templates)/),
|
||||
};
|
||||
|
||||
const isLocalhost = Boolean(
|
||||
window.location.hostname === 'localhost' ||
|
||||
// [::1] is the IPv6 localhost address.
|
||||
window.location.hostname === '[::1]' ||
|
||||
// 127.0.0.1/8 is considered localhost for IPv4.
|
||||
window.location.hostname.match(
|
||||
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
|
||||
)
|
||||
/* eslint-disable no-restricted-globals */
|
||||
precacheAndRoute(self.__WB_MANIFEST || []);
|
||||
self.__WB_DISABLE_DEV_DEBUG_LOGS = false;
|
||||
skipWaiting();
|
||||
clientsClaim();
|
||||
|
||||
// This route's caching seems too aggressive.
|
||||
// TODO(abhinav): Figure out if this is really necessary.
|
||||
// Maybe add the assets locally?
|
||||
registerRoute(({ url }) => {
|
||||
return (
|
||||
regexMap.shims.test(url.pathname) || regexMap.static3PAssets.test(url.href)
|
||||
);
|
||||
}, new CacheFirst());
|
||||
|
||||
registerRoute(({ url }) => {
|
||||
return regexMap.profile.test(url.pathname);
|
||||
}, new NetworkOnly());
|
||||
|
||||
registerRoute(({ url }) => {
|
||||
return regexMap.appViewPage.test(url.pathname);
|
||||
}, new StaleWhileRevalidate());
|
||||
|
||||
registerRoute(
|
||||
({ url }) => regexMap.providers.test(url.pathname),
|
||||
new CacheFirst({
|
||||
plugins: [
|
||||
new ExpirationPlugin({
|
||||
maxAgeSeconds: 1 * 60 * 60,
|
||||
}),
|
||||
],
|
||||
}),
|
||||
);
|
||||
|
||||
export function register(config) {
|
||||
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
|
||||
// The URL constructor is available in all browsers that support SW.
|
||||
const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
|
||||
if (publicUrl.origin !== window.location.origin) {
|
||||
// Our service worker won't work if PUBLIC_URL is on a different origin
|
||||
// from what our page is served on. This might happen if a CDN is used to
|
||||
// serve assets; see https://github.com/facebook/create-react-app/issues/2374
|
||||
return;
|
||||
}
|
||||
|
||||
window.addEventListener('load', () => {
|
||||
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
|
||||
|
||||
if (isLocalhost) {
|
||||
// This is running on localhost. Let's check if a service worker still exists or not.
|
||||
checkValidServiceWorker(swUrl, config);
|
||||
|
||||
// Add some additional logging to localhost, pointing developers to the
|
||||
// service worker/PWA documentation.
|
||||
navigator.serviceWorker.ready.then(() => {
|
||||
console.log(
|
||||
'This web app is being served cache-first by a service ' +
|
||||
'worker. To learn more, visit http://bit.ly/CRA-PWA'
|
||||
);
|
||||
});
|
||||
} else {
|
||||
// Is not localhost. Just register service worker
|
||||
registerValidSW(swUrl, config);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function registerValidSW(swUrl, config) {
|
||||
navigator.serviceWorker
|
||||
.register(swUrl)
|
||||
.then(registration => {
|
||||
registration.onupdatefound = () => {
|
||||
const installingWorker = registration.installing;
|
||||
if (installingWorker == null) {
|
||||
return;
|
||||
}
|
||||
installingWorker.onstatechange = () => {
|
||||
if (installingWorker.state === 'installed') {
|
||||
if (navigator.serviceWorker.controller) {
|
||||
// At this point, the updated precached content has been fetched,
|
||||
// but the previous service worker will still serve the older
|
||||
// content until all client tabs are closed.
|
||||
console.log(
|
||||
'New content is available and will be used when all ' +
|
||||
'tabs for this page are closed. See http://bit.ly/CRA-PWA.'
|
||||
);
|
||||
|
||||
// Execute callback
|
||||
if (config && config.onUpdate) {
|
||||
config.onUpdate(registration);
|
||||
}
|
||||
} else {
|
||||
// At this point, everything has been precached.
|
||||
// It's the perfect time to display a
|
||||
// "Content is cached for offline use." message.
|
||||
console.log('Content is cached for offline use.');
|
||||
|
||||
// Execute callback
|
||||
if (config && config.onSuccess) {
|
||||
config.onSuccess(registration);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error during service worker registration:', error);
|
||||
});
|
||||
}
|
||||
|
||||
function checkValidServiceWorker(swUrl, config) {
|
||||
// Check if the service worker can be found. If it can't reload the page.
|
||||
fetch(swUrl)
|
||||
.then(response => {
|
||||
// Ensure service worker exists, and that we really are getting a JS file.
|
||||
const contentType = response.headers.get('content-type');
|
||||
if (
|
||||
response.status === 404 ||
|
||||
(contentType != null && contentType.indexOf('javascript') === -1)
|
||||
) {
|
||||
// No service worker found. Probably a different app. Reload the page.
|
||||
navigator.serviceWorker.ready.then(registration => {
|
||||
registration.unregister().then(() => {
|
||||
window.location.reload();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
// Service worker found. Proceed as normal.
|
||||
registerValidSW(swUrl, config);
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
console.log(
|
||||
'No internet connection found. App is running in offline mode.'
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
export function unregister() {
|
||||
if ('serviceWorker' in navigator) {
|
||||
navigator.serviceWorker.ready.then(registration => {
|
||||
registration.unregister();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
52
app/client/start-https.sh
Executable file
52
app/client/start-https.sh
Executable file
|
|
@ -0,0 +1,52 @@
|
|||
#!/bin/bash
|
||||
|
||||
# run the following commands before the docker run command
|
||||
# brew install mkcert (if you don't already have it installed)
|
||||
# run the following commented command from the project root directory
|
||||
# cd docker && mkcert -install && mkcert "*.appsmith.com" && cd ..
|
||||
# If this returns a hash successfully, then you can access the application locally using https://dev.appsmith.com
|
||||
|
||||
if ! docker_loc="$(type -p "docker")" || [[ -z $docker_loc ]]; then
|
||||
echo "Could not find docker cli"
|
||||
exit
|
||||
fi
|
||||
|
||||
KEY_FILE=./docker/_wildcard.appsmith.com-key.pem
|
||||
CERT_FILE=./docker/_wildcard.appsmith.com.pem
|
||||
if ! test -f "$KEY_FILE" || ! test -f "$CERT_FILE"; then
|
||||
echo "
|
||||
KEY and/or CERTIFICATE not found
|
||||
Please install mkcert and generate
|
||||
the key and certificate files
|
||||
by running the following command
|
||||
|
||||
cd docker && mkcert -install && mkcert \"*.appsmith.com\" && cd ..
|
||||
|
||||
"
|
||||
exit
|
||||
fi
|
||||
|
||||
unameOut="$(uname -s)"
|
||||
case "${unameOut}" in
|
||||
Linux*) machine=Linux
|
||||
echo "
|
||||
Starting nginx for Linux...
|
||||
"
|
||||
sudo docker run --network host --name wildcard-nginx -d -p 80:80 -p 443:443 -v `pwd`/docker/nginx-linux.conf:/etc/nginx/conf.d/app.conf -v `pwd`/docker/_wildcard.appsmith.com.pem:/etc/certificate/dev.appsmith.com.pem -v `pwd`/docker/_wildcard.appsmith.com-key.pem:/etc/certificate/dev.appsmith.com-key.pem nginx:latest \
|
||||
&& echo "
|
||||
nginx is listening on port 443 and forwarding to port 3000
|
||||
visit https://dev.appsmith.com
|
||||
"
|
||||
;;
|
||||
Darwin*) machine=Mac
|
||||
echo "
|
||||
Starting nginx for MacOS...
|
||||
"
|
||||
docker run --name wildcard-nginx -d -p 80:80 -p 443:443 -v `pwd`/docker/nginx-mac.conf:/etc/nginx/conf.d/app.conf -v `pwd`/docker/_wildcard.appsmith.com.pem:/etc/certificate/dev.appsmith.com.pem -v `pwd`/docker/_wildcard.appsmith.com-key.pem:/etc/certificate/dev.appsmith.com-key.pem nginx:latest \
|
||||
&& echo "
|
||||
nginx is listening on port 443 and forwarding to port 3000
|
||||
visit https://dev.appsmith.com
|
||||
"
|
||||
;;
|
||||
*) echo "Unknown OS: Please use MacOS or a distribution of linux."
|
||||
esac
|
||||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user