diff --git a/index.html b/index.html index 8997335..96e638d 100644 --- a/index.html +++ b/index.html @@ -1,120 +1,20 @@ - - - - - - - - - - - - - - - - - - - sandspiel - - - - - - - - - + sandspiel + - - - - -
- - - diff --git a/js/app.js b/js/app.js index d3202b9..49473d2 100644 --- a/js/app.js +++ b/js/app.js @@ -1,63 +1,6 @@ import React from "react"; import ReactDOM from "react-dom"; -import { BrowserRouter as Router, Route, Link } from "react-router-dom"; -import Info from "./components/info"; import { Index } from "./components/ui"; -import Browse from "./components/browse"; -import Admin from "./components/admin"; -import Menu from "./components/menu"; -import SignInScreen from "./components/signin"; -import BenchmarkRunner from "./components/benchmarkRunner"; -let sizeMap = [2, 5, 10, 18, 30, 45]; - -function BrowseRouter({ match, location }) { - return ( - - - - ); -} - -function AdminRouter({ match, location }) { - return ( - - - - ); -} - -function SigninRouter({ match, location }) { - return ( - - - - ); -} - -function AppRouter() { - return ( - - - ( - - - - )} - /> - - - - - - - ); -} - -ReactDOM.render(, document.getElementById("ui")); - -export { sizeMap }; +ReactDOM.render(, document.getElementById("ui")); diff --git a/js/components/ui.js b/js/components/ui.js index 10d1bd6..f3dd7ef 100644 --- a/js/components/ui.js +++ b/js/components/ui.js @@ -1,19 +1,12 @@ import React from "react"; -import { Link } from "react-router-dom"; -import * as Sentry from "@sentry/browser"; import * as wasm from "../../crate/pkg/sandtable_bg.wasm"; import { Species } from "../../crate/pkg/sandtable"; const memory = wasm.memory; import { height, universe, width, reset } from "../index.js"; -import { snapshot, pallette } from "../render.js"; -import { functions, storage } from "../api.js"; -import SignInButton from "./signinButton.js"; +import { pallette } from "../render.js"; import { svgToImageData, rgbaToSpecies } from "../convertSVG"; -import { fetchVotedIds } from "../votes.js"; - -import Menu from "./menu"; window.species = Species; let pallette_data = pallette(); @@ -64,82 +57,23 @@ class Index extends React.Component { super(props); this.state = { - submissionMenuOpen: false, paused: false, - submitting: false, size: 2, - dataURL: {}, - currentSubmission: null, selectedElement: Species.Water, }; window.UI = this; - //if we start in the background, pause; - if ( - this.props.location.pathname !== "/" && - this.props.location.pathname !== "/school" - ) { - window.setTimeout(() => this.pause(), 50); - } - - this.load(); - } - - componentDidMount() { - this.unregisterAuthObserver = firebase.auth().onAuthStateChanged((user) => { - if (user && this.state.currentSubmission) { - this.checkLiked(this.state.currentSubmission.id); - } - }); } - componentWillUnmount() { - if (this.unregisterAuthObserver) { - this.unregisterAuthObserver(); - } - } - - // Marks the loaded submission as liked if the signed-in user already voted. - checkLiked(id) { - fetchVotedIds([id]).then((voted) => { - const { currentSubmission } = this.state; - if (voted.has(id) && currentSubmission && currentSubmission.id === id) { - this.setState({ - currentSubmission: { ...currentSubmission, liked: true }, - }); - } - }); - } - - componentDidUpdate(prevProps) { - if ( - this.props.location.pathname === "/" && - prevProps.location.pathname !== "/" && - this.state.currentSubmission - ) { - window.location = `#${this.state.currentSubmission.id}`; - return; - } - if ( - this.props.location.pathname !== "/" && - prevProps.location.pathname == "/" - ) { - this.pause(); - } - if ( - prevProps.location.hash === "" || - prevProps.location.hash != this.props.location.hash - ) { - this.load(); - } - } togglePause() { window.paused = !this.state.paused; this.setState({ paused: !this.state.paused }); } + play() { window.paused = false; this.setState({ paused: false }); } + pause() { window.paused = true; this.setState({ paused: true }); @@ -151,147 +85,13 @@ class Index extends React.Component { size, }); } + reset() { if (window.confirm("Are you sure you want to reset?")) { this.play(); - window.location = "#"; - this.setState({ currentSubmission: null }); reset(); } } - menu() { - this.pause(); - this.setState({ submissionMenuOpen: true }); - } - - closeMenu() { - this.play(); - this.setState({ submissionMenuOpen: false }); - } - upload() { - let dataURL = snapshot(universe); - const cells = new Uint8Array( - memory.buffer, - universe.cells(), - width * height * 4 - ); - - // Create canvas - let canvas = document.createElement("canvas"), - context = canvas.getContext("2d"), - imgData = context.createImageData(width, height); - - canvas.height = height; - canvas.width = width; - - // fill imgData with data from cells - // transpose for historical compatability - for (let x = 0; x < width; x++) { - for (let y = 0; y < height; y++) { - let cell_index = (y + x * height) * 4; - let img_index = (x + y * width) * 4; - for (var i = 0; i < 4; i++) { - if (i % 4 == 3) { - imgData.data[img_index + i] = 255; - } else { - imgData.data[img_index + i] = cells[cell_index + i]; - } - } - } - } - // put data to context at (0, 0) - context.putImageData(imgData, 0, 0); - - let cellData = canvas.toDataURL("image/png"); - - this.pause(); - this.setState({ - data: { dataURL, cells: cellData }, - submissionMenuOpen: true, - }); - } - rateLimited() { - var postList = JSON.parse(localStorage.getItem("postList") || "[]"); - postList = postList.filter((post) => Date.now() - 1000 * 60 * 5 < post); - - if (postList.length >= 3) { - Sentry.captureMessage("RATELIMIT"); - return true; - } - return false; - } - submit() { - let { title = "", data, currentSubmission } = this.state; - - let { dataURL, cells } = data; - let { currentUser } = firebase.auth(); - if (!currentUser) { - window.alert("Please sign in to post!"); - return; - } - title = title.replace( - "[profile]", - `https://sandspiel.club/browse/search/?user=${currentUser.uid}` - ); - - let payload = { - title, - image: dataURL, - parent_id: currentSubmission?.data?.id, - cells, - }; - - const recordPost = () => { - var postList = JSON.parse(localStorage.getItem("postList") || "[]"); - postList = postList.filter((post) => Date.now() - 1000 * 60 * 3 < post); - postList.push(Date.now()); - localStorage.setItem("postList", JSON.stringify(postList)); - }; - - const errorMessages = { - 202: "This exact creation has already been posted.", - 301: "Please verify your email address before posting.", - 302: "Too many posts from your network today. Try again later.", - 400: "This creation couldn't be validated. Try uploading again.", - 401: "Your account has been banned from posting.", - 418: "That title isn't allowed. Please choose another.", - 429: "You're posting too fast. Wait a few minutes and try again.", - }; - - this.setState({ submitting: true }); - currentUser - .getIdToken() - .then((token) => - fetch(functions._url("api/creations"), { - method: "POST", - body: JSON.stringify(payload), // data can be `string` or {object}! - headers: { - "Content-Type": "application/json", - Authorization: "Bearer " + token, - }, - }) - ) - .then((res) => { - if (!res.ok) { - throw new Error( - errorMessages[res.status] || - `Upload failed (HTTP ${res.status}). Please try again.` - ); - } - return res.json(); - }) - .then((response) => { - console.log("Success:", JSON.stringify(response)); - recordPost(); - this.setState({ submissionMenuOpen: false, submitting: false }); - this.play(); - }) - .catch((error) => { - console.error("Error:", error); - window.alert(error.message || "Upload failed. Please try again."); - this.setState({ submitting: false }); - }); - } async loadSVG(svgString) { const imgData = await svgToImageData(svgString); @@ -323,150 +123,8 @@ class Index extends React.Component { this.pause(); } - load() { - let { location } = this.props; - let id = location.hash.replace(/#/, ""); - if (id === "") { - return; - } - - if (this.state.currentSubmission && this.state.currentSubmission.id == id) { - return; - } - - fetch(functions._url(`api/creations/${id}`), { - method: "GET", - headers: { - "Content-Type": "application/json", - }, - }) - .then((res) => { - if (!res.ok) throw new Error(`HTTP ${res.status}`); - return res.json(); - }) - .then((data) => { - if (!data || !data.id) throw new Error("submission not found"); - storage - .refFromURL( - `gs://sandtable-8d0f7.appspot.com/creations/${data.id}.data.png` - ) - .getDownloadURL() - .then((dlurl) => { - fetch(dlurl, { - method: "GET", - }) - .then((res) => res.blob()) - .then((blob) => { - this.setState({ currentSubmission: { id, data } }); - this.checkLiked(id); - - var url = URL.createObjectURL(blob); - var img = new Image(); - img.src = url; - img.onload = () => { - var canvas = document.createElement("canvas"); - canvas.width = width; - canvas.height = height; - var ctx = canvas.getContext("2d"); - - ctx.translate(canvas.width / 2, canvas.height / 2); - ctx.rotate((-90 * Math.PI) / 180); - ctx.scale(-1, 1.0); - ctx.translate(-canvas.width / 2, -canvas.height / 2); - - ctx.drawImage(img, 0, 0); - var imgData = ctx.getImageData( - 0, - 0, - canvas.width, - canvas.height - ); - - const cellsData = new Uint8Array( - memory.buffer, - universe.cells(), - width * height * 4 - ); - - reset(); - window.stopboot = true; - - for (var i = 0; i < width * height * 4; i++) { - cellsData[i] = imgData.data[i]; - } - universe.flush_undos(); - universe.push_undo(); - this.pause(); - }; - }) - .catch((error) => console.error("Error:", error)); - }) - .catch((error) => console.error("Error:", error)); - }) - .catch((error) => { - console.error("Error:", error); - }); - } - incScore() { - let { currentSubmission } = this.state; - if (!currentSubmission || currentSubmission.liked) return; - let { id } = currentSubmission; - const { currentUser } = firebase.auth(); - if (!currentUser) { - window.alert("Please sign in to vote!"); - return; - } - if (!currentUser.emailVerified) { - window.alert(`Please verify your email ${currentUser.email} to vote!`); - return; - } - // creations/:id/vote - currentUser - .getIdToken() - .then((token) => - fetch(functions._url(`api/creations/${id}/vote`), { - method: "PUT", - headers: { - "Content-Type": "application/json", - Authorization: "Bearer " + token, - }, - }) - ) - .then((res) => { - if (res.status === 301) { - // already voted: just reflect that - if (this.state.currentSubmission?.id === id) { - this.setState({ - currentSubmission: { ...this.state.currentSubmission, liked: true }, - }); - } - return null; - } - if (!res.ok) throw new Error(`HTTP ${res.status}`); - return res.json(); - }) - .then((data) => { - if (data && this.state.currentSubmission?.id === id) { - this.setState({ - currentSubmission: { - ...this.state.currentSubmission, - data, - liked: true, - }, - }); - } - }) - .catch((e) => { - console.error(e); - }); - } - render() { - let { size, paused, selectedElement, currentSubmission } = this.state; - let hash = - currentSubmission && currentSubmission.id - ? `#${currentSubmission.id}` - : ""; + let { size, paused, selectedElement } = this.state; return ( - - - - - )} - - - - - {/* {paused && } */} {sizeMap.map((v, i) => ( @@ -549,52 +184,6 @@ class Index extends React.Component { this.setState({ selectedElement: id }) ) )} - {/* - *new*{" "} - - orb.farm - - */} - {this.state.currentSubmission && ( -
- - {this.state.currentSubmission.data.title} -
- )} - - {this.state.submissionMenuOpen && ( - this.closeMenu()}> -

Share your creation with the people! (try using #hashtags)

-

- Please be nice. Users who post hateful or sexually explicit - content will be banned. -

- - -
- this.setState({ title: e.target.value })} - /> - -
-
-
- )}
); } diff --git a/js/index.js b/js/index.js index 22a8793..0882dbb 100644 --- a/js/index.js +++ b/js/index.js @@ -1,24 +1,6 @@ -import * as Sentry from "@sentry/browser"; -import { Integrations } from "@sentry/tracing"; -import { Wasm as WasmIntegration } from "@sentry/wasm"; import { boot } from "./boot"; -if (!window.location.host.startsWith("localhost")) { - Sentry.init({ - dsn: "https://4bf8c3ab764f40569d573fc4021efe40@o40136.ingest.sentry.io/1331284", - - // Alternatively, use `process.env.npm_package_version` for a dynamic release version - // if your build tool supports it. - integrations: [new Integrations.BrowserTracing(), new WasmIntegration()], - - // Set tracesSampleRate to 1.0 to capture 100% - // of transactions for performance monitoring. - // We recommend adjusting this value in production - tracesSampleRate: 0.01, - }); -} - -import "./api"; import { Universe } from "../crate/pkg"; +import * as wasm from "../crate/pkg/sandtable_bg.wasm"; import { startWebGL } from "./render"; import { fps } from "./fps"; @@ -27,49 +9,7 @@ import {} from "./app"; import { startFluid } from "./fluid"; import {} from "./layout"; -const isBench = window.location.pathname === "/bench"; -if (window.safari) { - history.pushState(null, null, location.href); - window.onpopstate = function (event) { - history.go(1); - }; -} - -function mobileAndTabletcheck() { - var check = false; - (function (a) { - if ( - /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test( - a - ) || - /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test( - a.substr(0, 4) - ) - ) - check = true; - })(navigator.userAgent || navigator.vendor || window.opera); - return check; -} - -if (mobileAndTabletcheck()) { - window.onbeforeunload = function () { - return true; - }; -} - -if ("serviceWorker" in navigator) { - window.addEventListener("load", () => { - navigator.serviceWorker - .register("/service-worker.js") - .then((registration) => { - console.log("SW registered: ", registration); - fetch("index.html"); // refresh cache (?) - }) - .catch((registrationError) => { - console.log("SW registration failed: ", registrationError); - }); - }); -} +const isBench = false; let n = 300; const universe = isBench ? window.u : Universe.new(n, n); @@ -82,7 +22,7 @@ const canvas2 = document.getElementById("fluid-canvas"); canvas.height = n * Math.ceil(window.devicePixelRatio); canvas.width = n * Math.ceil(window.devicePixelRatio); -document.getElementById("background").addEventListener("touchmove", (e) => { +canvas.addEventListener("touchmove", (e) => { if (!window.paused) { if (e.cancelable) { e.preventDefault(); @@ -140,5 +80,29 @@ document.addEventListener("paste", function (event) { } }); -(adsbygoogle = window.adsbygoogle || []).push({}); +// For the page that embeds this one (wasmga.me): the board as bytes, to keep +// and to load back, and a reset without asking. +const cells = () => + new Uint8Array(wasm.memory.buffer, universe.cells(), width * height * 4); +window.wg = { + snapshot: () => cells().slice(), + restore(bytes) { + if (bytes.length !== width * height * 4) return false; + reset(); + window.stopboot = true; + cells().set(bytes); + universe.flush_undos(); + universe.push_undo(); + return true; + }, + clear() { + window.stopboot = true; + reset(); + }, + setPaused(paused) { + if (paused) window.UI.pause(); + else window.UI.play(); + }, +}; + export { canvas, width, height, universe, reset }; diff --git a/js/layout.js b/js/layout.js index ac72c17..a928c86 100644 --- a/js/layout.js +++ b/js/layout.js @@ -1,3 +1,6 @@ +// Fits the board and the buttons into the window: the buttons beside the +// board when there's room for them, else in one row above it that scrolls +// sideways. let resize = () => { const canvas = document.getElementById("sand-canvas"); const canvas2 = document.getElementById("fluid-canvas"); @@ -5,50 +8,26 @@ let resize = () => { if (!canvas || !canvas2 || !ui) return; - let screen_width = window.innerWidth; - let uiheight = 50; - let screen_height = window.innerHeight - uiheight; - - let canvasStyle = ""; - let uiStyle = ""; - let adStyle = "display:none;"; - - if (screen_width > screen_height) { - if (screen_width - window.innerHeight < 400) { - // landscape compressed - canvasStyle = `height: ${window.innerHeight}px; margin:3px`; - uiStyle = `width: ${ - screen_width - window.innerHeight - 12 - }px; margin: 2px;`; - } else { - // landscape wide - canvasStyle = ` - height: ${window.innerHeight}px; - width:${window.innerHeight}px; - margin:0; - left: auto; - right: 206px`; - uiStyle = `width: 200px; margin: 2px;`; - adStyle = `width: ${ - screen_width - window.innerHeight - (206 + 150) - }px; margin: 1px;`; - } + const w = window.innerWidth; + const h = window.innerHeight; + let side; + if (w - h >= 180) { + ui.className = ""; + ui.style = `width: ${w - h - 8}px; margin: 2px;`; + side = h; + canvas.style = canvas2.style = `height: ${side}px; width: ${side}px; left: 0; right: auto;`; } else { - //portrait (mobile) - canvasStyle = `width: ${screen_width}px; bottom:3px;`; - uiStyle = ""; + ui.className = "row"; + ui.style = ""; + side = Math.max(60, Math.min(w, h - ui.offsetHeight - 2)); + canvas.style = canvas2.style = `height: ${side}px; width: ${side}px;`; } - ui.style = uiStyle; - canvas.style = canvasStyle; - canvas2.style = canvasStyle; - const adSlot = document.getElementsByClassName("adslot_1")[0]; - if (adSlot) adSlot.style = adStyle; }; -if (document.readyState === 'loading') { - document.addEventListener('DOMContentLoaded', resize); +if (document.readyState === "loading") { + document.addEventListener("DOMContentLoaded", resize); } else { resize(); } -window.addEventListener("deviceorientation", resize, true); window.addEventListener("resize", resize); +new ResizeObserver(resize).observe(document.getElementById("ui")); diff --git a/js/styles.css b/js/styles.css index 309c533..2ab8465 100644 --- a/js/styles.css +++ b/js/styles.css @@ -431,3 +431,17 @@ img { .reversed { transform: rotate(180deg); } + +#ui.row { + float: none; + flex-wrap: nowrap; + overflow-x: auto; + scrollbar-width: none; +} +#ui.row button { + flex-shrink: 0; +} +#ui.row .sizes { + display: flex; + flex-shrink: 0; +} diff --git a/package.json b/package.json index 8860e0c..e2bccac 100644 --- a/package.json +++ b/package.json @@ -4,9 +4,7 @@ "description": "", "main": "index.js", "scripts": { - "build": "webpack --mode=production", - "start": "webpack-dev-server --host 0.0.0.0", - "deploy": "webpack --mode=production && gh-pages -d dist" + "build": "webpack --mode=production" }, "repository": { "type": "git", @@ -25,44 +23,29 @@ "@babel/plugin-syntax-dynamic-import": "^7.7.4", "@babel/preset-env": "^7.7.7", "@babel/preset-react": "^7.7.4", - "@wasm-tool/wasm-pack-plugin": "0.2.1", "babel-loader": "^8.0.6", "copy-webpack-plugin": "^12.0.2", "glslify": "^6.4.1", "glslify-loader": "^1.0.2", "html-webpack-plugin": "^5.6.5", - "http-server": "^0.11.1", "raw-loader": "^1.0.0", "webpack": "^5.104.1", - "webpack-cli": "^5.1.4", - "webpack-dev-server": "^5.2.3", - "workbox-webpack-plugin": "^7.4.0" + "webpack-cli": "^5.1.4" }, "dependencies": { "@babel/plugin-proposal-class-properties": "^7.7.4", "@babel/plugin-transform-runtime": "^7.13.15", - "@sentry/browser": "^6.2.5", - "@sentry/react": "^7.28.1", - "@sentry/tracing": "^6.2.5", - "@sentry/wasm": "^6.2.5", + "@babel/runtime": "^7.29.10", "classnames": "^2.2.6", "clean-webpack-plugin": "^4.0.0", "css-loader": "^5.0.2", "dat.gui": "^0.7.5", - "firebase": "^8.2.8", - "firebase-admin": "^9.3.0", - "firebase-tools": "^15.29.0", - "gh-pages": "^2.1.1", "glsl-hsv2rgb": "^1.0.0", "glsl-noise": "0.0.0", "glsl-random": "0.0.5", "react": "^16.12.0", "react-dom": "^16.12.0", - "react-firebaseui": "4.1.0", - "react-router-dom": "^5.1.2", - "react-youtube": "^9.0.2", "regl": "^1.3.13", - "style-loader": "^2.0.0", - "timeago.js": "^3.0.2" + "style-loader": "^2.0.0" } } diff --git a/webpack.config.js b/webpack.config.js index 28c87ab..ca0fda7 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -2,62 +2,27 @@ const path = require("path"); const dist = path.resolve(__dirname, "dist"); const CopyWebpackPlugin = require("copy-webpack-plugin"); -const WasmPackPlugin = require("@wasm-tool/wasm-pack-plugin"); const HtmlWebpackPlugin = require("html-webpack-plugin"); const { CleanWebpackPlugin } = require("clean-webpack-plugin"); -const { GenerateSW } = require("workbox-webpack-plugin"); module.exports = (env, argv) => { const isProduction = argv.mode === "production"; const plugins = [ new CleanWebpackPlugin(), - new WasmPackPlugin({ - crateDirectory: path.resolve(__dirname, "crate"), - extraArgs: "--target bundler", - }), new CopyWebpackPlugin({ - patterns: [ - "js/styles.css", - "manifest.json", - { from: "assets/*" }, - ], + patterns: ["js/styles.css"], }), new HtmlWebpackPlugin({ template: "index.html" }), ]; - // Only add service worker in production to avoid watch mode warnings - if (isProduction) { - plugins.push( - new GenerateSW({ - navigateFallback: "index.html", - runtimeCaching: [ - { - urlPattern: /\.html$/, - handler: "StaleWhileRevalidate", - }, - { - urlPattern: /\.(?:png|jpg|jpeg|svg)$/, - handler: "CacheFirst", - options: { - cacheName: "images", - expiration: { - maxEntries: 300, - }, - }, - }, - ], - }) - ); - } - return { entry: "./js/bootstrap.js", output: { path: dist, - filename: "[name].[contenthash].js", - publicPath: "/", + filename: "[name].js", + publicPath: "", }, devServer: { static: dist, @@ -68,7 +33,7 @@ module.exports = (env, argv) => { asyncWebAssembly: true, }, mode: isProduction ? "production" : "development", - devtool: "source-map", + devtool: false, plugins, module: { rules: [