refactor: change SPA to MPA
This commit is contained in:
Vendored
+4
-1
@@ -53,5 +53,8 @@
|
|||||||
"webrowse"
|
"webrowse"
|
||||||
],
|
],
|
||||||
"reactSnippets.settings.prettierEnabled": true,
|
"reactSnippets.settings.prettierEnabled": true,
|
||||||
"reactSnippets.settings.importReactOnTop": false
|
"reactSnippets.settings.importReactOnTop": false,
|
||||||
|
"[html]": {
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,6 +58,8 @@ module.exports = {
|
|||||||
appPublic: resolveApp("public"),
|
appPublic: resolveApp("public"),
|
||||||
appHtml: resolveApp("public/index.html"),
|
appHtml: resolveApp("public/index.html"),
|
||||||
appIndexJs: resolveModule(resolveApp, "src/index"),
|
appIndexJs: resolveModule(resolveApp, "src/index"),
|
||||||
|
embedAppHtml: resolveApp("public/embed.html"),
|
||||||
|
embedAppIndexJs: resolveModule(resolveApp, "src/embed"),
|
||||||
appPackageJson: resolveApp("package.json"),
|
appPackageJson: resolveApp("package.json"),
|
||||||
appSrc: resolveApp("src"),
|
appSrc: resolveApp("src"),
|
||||||
appTsConfig: resolveApp("tsconfig.json"),
|
appTsConfig: resolveApp("tsconfig.json"),
|
||||||
|
|||||||
+32
-15
@@ -118,7 +118,7 @@ module.exports = function (webpackEnv) {
|
|||||||
: isEnvDevelopment && "cheap-module-source-map",
|
: isEnvDevelopment && "cheap-module-source-map",
|
||||||
// These are the "entry points" to our application.
|
// These are the "entry points" to our application.
|
||||||
// This means they will be the "root" imports that are included in JS bundle.
|
// This means they will be the "root" imports that are included in JS bundle.
|
||||||
entry: paths.appIndexJs,
|
entry: { main: paths.appIndexJs, embed: paths.embedAppIndexJs },
|
||||||
output: {
|
output: {
|
||||||
// The build folder.
|
// The build folder.
|
||||||
path: paths.appBuild,
|
path: paths.appBuild,
|
||||||
@@ -128,7 +128,7 @@ module.exports = function (webpackEnv) {
|
|||||||
// In development, it does not produce real files.
|
// In development, it does not produce real files.
|
||||||
filename: isEnvProduction
|
filename: isEnvProduction
|
||||||
? "static/js/[name].[contenthash:8].js"
|
? "static/js/[name].[contenthash:8].js"
|
||||||
: isEnvDevelopment && "static/js/bundle.js",
|
: isEnvDevelopment && "static/js/[name].bundle.js",
|
||||||
// There are also additional JS chunk files if you use code splitting.
|
// There are also additional JS chunk files if you use code splitting.
|
||||||
chunkFilename: isEnvProduction
|
chunkFilename: isEnvProduction
|
||||||
? "static/js/[name].[contenthash:8].chunk.js"
|
? "static/js/[name].[contenthash:8].chunk.js"
|
||||||
@@ -260,18 +260,6 @@ module.exports = function (webpackEnv) {
|
|||||||
// match the requirements. When no loader matches it will fall
|
// match the requirements. When no loader matches it will fall
|
||||||
// back to the "file" loader at the end of the loader list.
|
// back to the "file" loader at the end of the loader list.
|
||||||
oneOf: [
|
oneOf: [
|
||||||
// TODO: Merge this config once `image/avif` is in the mime-db
|
|
||||||
// https://github.com/jshttp/mime-db
|
|
||||||
{
|
|
||||||
test: [/\.avif$/],
|
|
||||||
type: "asset",
|
|
||||||
mimetype: "image/avif",
|
|
||||||
parser: {
|
|
||||||
dataUrlCondition: {
|
|
||||||
maxSize: imageInlineSizeLimit
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// "url" loader works like "file" loader except that it embeds assets
|
// "url" loader works like "file" loader except that it embeds assets
|
||||||
// smaller than specified limit in bytes as data URLs to avoid requests.
|
// smaller than specified limit in bytes as data URLs to avoid requests.
|
||||||
// A missing `test` is equivalent to a match.
|
// A missing `test` is equivalent to a match.
|
||||||
@@ -409,8 +397,37 @@ module.exports = function (webpackEnv) {
|
|||||||
Object.assign(
|
Object.assign(
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
|
filename: "index.html",
|
||||||
inject: true,
|
inject: true,
|
||||||
template: paths.appHtml
|
template: paths.appHtml,
|
||||||
|
chunks: ["main"]
|
||||||
|
},
|
||||||
|
isEnvProduction
|
||||||
|
? {
|
||||||
|
minify: {
|
||||||
|
removeComments: true,
|
||||||
|
collapseWhitespace: true,
|
||||||
|
removeRedundantAttributes: true,
|
||||||
|
useShortDoctype: true,
|
||||||
|
removeEmptyAttributes: true,
|
||||||
|
removeStyleLinkTypeAttributes: true,
|
||||||
|
keepClosingSlash: true,
|
||||||
|
minifyJS: true,
|
||||||
|
minifyCSS: true,
|
||||||
|
minifyURLs: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
: undefined
|
||||||
|
)
|
||||||
|
),
|
||||||
|
new HtmlWebpackPlugin(
|
||||||
|
Object.assign(
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
filename: "embed.html",
|
||||||
|
inject: true,
|
||||||
|
template: paths.embedAppHtml,
|
||||||
|
chunks: ["embed"]
|
||||||
},
|
},
|
||||||
isEnvProduction
|
isEnvProduction
|
||||||
? {
|
? {
|
||||||
|
|||||||
@@ -0,0 +1,116 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<meta name="theme-color" content="#527ff1" />
|
||||||
|
<meta name="description" content="Your private chat APP" />
|
||||||
|
<link rel="apple-touch-icon" href="%PUBLIC_URL%/apple-touch-icon.png" />
|
||||||
|
<!-- splash -->
|
||||||
|
<link
|
||||||
|
href="%PUBLIC_URL%/splash/iphone5_splash.png"
|
||||||
|
media="(device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2)"
|
||||||
|
rel="apple-touch-startup-image"
|
||||||
|
/>
|
||||||
|
<link
|
||||||
|
href="%PUBLIC_URL%/splash/iphone6_splash.png"
|
||||||
|
media="(device-width: 375px) and (device-height: 667px) and (-webkit-device-pixel-ratio: 2)"
|
||||||
|
rel="apple-touch-startup-image"
|
||||||
|
/>
|
||||||
|
<link
|
||||||
|
href="%PUBLIC_URL%/splash/iphoneplus_splash.png"
|
||||||
|
media="(device-width: 621px) and (device-height: 1104px) and (-webkit-device-pixel-ratio: 3)"
|
||||||
|
rel="apple-touch-startup-image"
|
||||||
|
/>
|
||||||
|
<link
|
||||||
|
href="%PUBLIC_URL%/splash/iphonex_splash.png"
|
||||||
|
media="(device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3)"
|
||||||
|
rel="apple-touch-startup-image"
|
||||||
|
/>
|
||||||
|
<link
|
||||||
|
href="%PUBLIC_URL%/splash/iphonexr_splash.png"
|
||||||
|
media="(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 2)"
|
||||||
|
rel="apple-touch-startup-image"
|
||||||
|
/>
|
||||||
|
<link
|
||||||
|
href="%PUBLIC_URL%/splash/iphonexsmax_splash.png"
|
||||||
|
media="(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 3)"
|
||||||
|
rel="apple-touch-startup-image"
|
||||||
|
/>
|
||||||
|
<link
|
||||||
|
href="%PUBLIC_URL%/splash/ipad_splash.png"
|
||||||
|
media="(device-width: 768px) and (device-height: 1024px) and (-webkit-device-pixel-ratio: 2)"
|
||||||
|
rel="apple-touch-startup-image"
|
||||||
|
/>
|
||||||
|
<link
|
||||||
|
href="%PUBLIC_URL%/splash/ipadpro1_splash.png"
|
||||||
|
media="(device-width: 834px) and (device-height: 1112px) and (-webkit-device-pixel-ratio: 2)"
|
||||||
|
rel="apple-touch-startup-image"
|
||||||
|
/>
|
||||||
|
<link
|
||||||
|
href="%PUBLIC_URL%/splash/ipadpro3_splash.png"
|
||||||
|
media="(device-width: 834px) and (device-height: 1194px) and (-webkit-device-pixel-ratio: 2)"
|
||||||
|
rel="apple-touch-startup-image"
|
||||||
|
/>
|
||||||
|
<link
|
||||||
|
href="%PUBLIC_URL%/splash/ipadpro2_splash.png"
|
||||||
|
media="(device-width: 1024px) and (device-height: 1366px) and (-webkit-device-pixel-ratio: 2)"
|
||||||
|
rel="apple-touch-startup-image"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- /splash -->
|
||||||
|
<!--
|
||||||
|
manifest.json provides metadata used when your web app is installed on a
|
||||||
|
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
||||||
|
-->
|
||||||
|
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
||||||
|
<!-- <link rel="manifest" id="my-manifest-placeholder"> -->
|
||||||
|
<!--
|
||||||
|
Notice the use of %PUBLIC_URL% in the tags above.
|
||||||
|
It will be replaced with the URL of the `public` folder during the build.
|
||||||
|
Only files inside the `public` folder can be referenced from the HTML.
|
||||||
|
|
||||||
|
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
||||||
|
work correctly both with client-side routing and a non-root public URL.
|
||||||
|
Learn how to configure a non-root public URL by running `npm run build`.
|
||||||
|
-->
|
||||||
|
<title>VoceChat Embed</title>
|
||||||
|
<style>
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
|
||||||
|
Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif !important;
|
||||||
|
/* pointer-events: none; */
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<style>
|
||||||
|
/* reset */
|
||||||
|
* {
|
||||||
|
overflow: visible;
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
/* user-select: none; */
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||||
|
<div id="root"></div>
|
||||||
|
<div id="root-modal"></div>
|
||||||
|
<div id="modal-modal"></div>
|
||||||
|
<!--
|
||||||
|
This HTML file is a template.
|
||||||
|
If you open it directly in the browser, you will see an empty page.
|
||||||
|
|
||||||
|
You can add webfonts, meta tags, or analytics to this file.
|
||||||
|
The build step will place the bundled scripts into the <body> tag.
|
||||||
|
|
||||||
|
To begin the development, run `npm start` or `yarn start`.
|
||||||
|
To create a production bundle, use `npm run build` or `yarn build`.
|
||||||
|
-->
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Vocechat Embed Demo</title>
|
||||||
|
</head>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
cursor: pointer;
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
background-color: azure;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vocechat_ifr {
|
||||||
|
/* pointer-events: none; */
|
||||||
|
position: fixed;
|
||||||
|
right: 15px;
|
||||||
|
bottom: 15px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div class="vocechat_ifr">
|
||||||
|
<iframe width="100%" height="100%" src="//localhost:3009/embed.html" frameborder="0"></iframe>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import ReactDOM from "react-dom/client";
|
||||||
|
import { Reset } from "styled-reset";
|
||||||
|
import Embed from "./embed/index";
|
||||||
|
import "./assets/base.css";
|
||||||
|
import MarkdownStyleOverride from "./common/component/MarkdownStyleOverride";
|
||||||
|
|
||||||
|
const root = ReactDOM.createRoot(document.getElementById("root") as HTMLElement);
|
||||||
|
|
||||||
|
root.render(
|
||||||
|
<>
|
||||||
|
<Reset />
|
||||||
|
<Embed />
|
||||||
|
<MarkdownStyleOverride />
|
||||||
|
</>
|
||||||
|
);
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import React from "react";
|
||||||
|
import styled from "styled-components";
|
||||||
|
const Styled = styled.section`
|
||||||
|
width: 800px;
|
||||||
|
height: 800px;
|
||||||
|
`;
|
||||||
|
type Props = {};
|
||||||
|
|
||||||
|
const Chat = (props: Props) => {
|
||||||
|
return <Styled>Chat</Styled>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Chat;
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import { useState } from "react";
|
||||||
|
import styled from "styled-components";
|
||||||
|
const Styled = styled.aside`
|
||||||
|
pointer-events: all;
|
||||||
|
`;
|
||||||
|
import Chat from "./Chat";
|
||||||
|
type Props = {};
|
||||||
|
|
||||||
|
function Embed({}: Props) {
|
||||||
|
const [visible, setVisible] = useState(false);
|
||||||
|
const toggleVisible = () => {
|
||||||
|
setVisible((prev) => !prev);
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<Styled>
|
||||||
|
<button onClick={toggleVisible}>{visible ? "close" : "open"}</button>
|
||||||
|
{visible && <Chat />}
|
||||||
|
</Styled>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Embed;
|
||||||
Reference in New Issue
Block a user