v2 Enable local development (#52)

- Create local dev environment
- Add gas-client and google-apps-script-webpack-dev-server packages for development
- Add dev/ wrapper app
- Update webpack config to support development environment
- Redesigned READMEs
- Support typescript
- Update npm scripts
- Organize and update .gitignore file
- Add .vscode settings for clasp files
- Remove tracking for files in dist/
This commit is contained in:
Elisha Nuchi
2020-08-15 13:09:04 -04:00
committed by GitHub
parent 5030a2f81e
commit 35a641d0f7
30 changed files with 5392 additions and 1742 deletions
+9
View File
@@ -0,0 +1,9 @@
{
"presets": [
"@babel/react"
],
"plugins": [
"@babel/plugin-proposal-object-rest-spread",
"@babel/plugin-proposal-class-properties"
]
}
+44
View File
@@ -0,0 +1,44 @@
{
"root": true,
"parser": "babel-eslint",
"extends": [
"airbnb-base",
"plugin:prettier/recommended",
"plugin:react/recommended"
],
"plugins": ["babel", "react", "prettier"],
"env": {
"browser": true,
"es6": true
},
"globals": {
"google": false,
"alert": false,
"css": true
},
"parserOptions": {
"ecmaVersion": 9,
"sourceType": "module",
"ecmaFeatures": {
"jsx": true
}
},
"rules": {
"prettier/prettier": "error",
"react/prop-types": "warn",
"camelcase": "warn",
"import/prefer-default-export": "warn",
"import/no-extraneous-dependencies": "warn",
"prefer-object-spread": "warn"
},
"settings": {
"react": {
"version": "detect"
},
"import/resolver": {
"node": {
"extensions": [".js", ".jsx"]
}
}
}
}
+15
View File
@@ -0,0 +1,15 @@
# Development App Wrapper
This directory contains the app needed to run development mode.
It utilizes special Webpack configurations as well as two packages, [gas-client](https://github.com/enuchi/gas-client) and [Webpack Dev Server for Google Apps Script](https://github.com/enuchi/Google-Apps-Script-Webpack-Dev-Server), in order to achieve hot reloading inside of a dialog window.
## How it works
Running `npm run start` will build and deploy the development app, and then serve files locally.
The simple React app in this directory, found at [index.js](./index.js), is designed to only be used with development builds. It loads an iframe with the source pointing to `https://localhost:${PORT}/gas/${FILENAME}-impl.html`. During the build step, we will replace `FILENAME` with the appropriate name of the HTML file to load.
As an example, during the development build, the file `dialog-demo-bootstrap.html` will be generated from the app in this directory, using `dialog-demo-bootstrap` as the `FILENAME` for the iframe source of this page. Opening the menu items in the Google Spreadsheet will load this app, and webpack's devServer settings will serve `https://localhost:3000/gas/dialog-demo-bootstrap-impl.html` within the iframe, using the customized Webpack Dev Server build.
The customized Google Apps Script Webpack Dev Server acts very similarly to Webpack Dev Server's iframe mode, but is able to pass requests to Google Apps Script server functions back and forth between all the iframes being used in development.
+19
View File
@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<base target="_top" />
<!-- Add any external scripts and stylesheets here -->
<style>
body,
html {
margin: 0;
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<section id="index" />
<!-- bundled js and css will get inlined here during build -->
</body>
</html>
+66
View File
@@ -0,0 +1,66 @@
import React, { useEffect } from 'react';
import ReactDOM from 'react-dom';
import server from '../src/client/utils/server';
const { serverFunctions } = server;
const { FILENAME, PORT } = process.env;
const DevServer = () => {
const iframe = React.useRef(null);
useEffect(() => {
const handleRequest = event => {
const request = event.data;
const { type, functionName, id, args } = request;
if (type !== 'REQUEST') return;
serverFunctions[functionName](...args)
.then(response => {
iframe.current.contentWindow.postMessage(
{ type: 'RESPONSE', id, status: 'SUCCESS', response },
`https://localhost:${PORT}`
);
})
.catch(err => {
iframe.current.contentWindow.postMessage(
{
type: 'RESPONSE',
id,
status: 'ERROR',
response: err,
},
`https://localhost:${PORT}`
);
});
};
window.addEventListener('message', handleRequest, false);
}, []);
return (
<div
// we want our dev environment to fill the dialog window
style={{
width: '100%',
height: '100%',
}}
>
<iframe
style={{
width: '100%',
height: '100%',
border: '0',
position: 'absolute',
}}
ref={iframe}
// The "/gas/" path here must match the path where the custom dev server is being loaded.
// See webpack.config.js "devServer" "before" settings.
// Filename extension "-impl" must match webpack.config.js clientConfigs filename settings for development.
src={`https://localhost:${PORT}/gas/${FILENAME}-impl.html`}
/>
</div>
);
};
ReactDOM.render(<DevServer />, document.getElementById('index'));