diff --git a/next.config.js b/next.config.js index 4e2e77fa0..936bce648 100644 --- a/next.config.js +++ b/next.config.js @@ -1,8 +1,9 @@ const { ProvidePlugin } = require('webpack'); -const { ESBuildMinifyPlugin } = require('esbuild-loader'); const bsconfig = require("./bsconfig.json"); -const path = require("path"); +const SSRPlugin = require("next/dist/build/webpack/plugins/nextjs-ssr-import") + .default; +const { dirname, relative, resolve, join } = require("path"); const remarkSlug = require("remark-slug"); const fs = require("fs"); @@ -17,17 +18,42 @@ const withMdx = require("./plugins/next-mdx")({ }); -// esbuild-loader specific features -// See: https://github.com/privatenumber/esbuild-loader-examples/blob/master/examples/next/next.config.js -function useEsbuildMinify(config, options) { - const terserIndex = config.optimization.minimizer.findIndex(minimizer => (minimizer.constructor.name === 'TerserPlugin')); - if (terserIndex > -1) { - config.optimization.minimizer.splice( - terserIndex, - 1, - new ESBuildMinifyPlugin(options), - ); - } +// Unfortunately there isn't an easy way to override the replacement function body, so we +// have to just replace the whole plugin `apply` body. +function patchSsrPlugin(plugin) { + plugin.apply = function apply(compiler) { + compiler.hooks.compilation.tap("NextJsSSRImport", compilation => { + compilation.mainTemplate.hooks.requireEnsure.tap( + "NextJsSSRImport", + (code, chunk) => { + // This is the block that fixes https://github.com/vercel/next.js/issues/22581 + if (!chunk.name) { + return; + } + + // Update to load chunks from our custom chunks directory + const outputPath = resolve("/"); + const pagePath = join("/", dirname(chunk.name)); + const relativePathToBaseDir = relative(pagePath, outputPath); + // Make sure even in windows, the path looks like in unix + // Node.js require system will convert it accordingly + const relativePathToBaseDirNormalized = relativePathToBaseDir.replace( + /\\/g, + "/" + ); + return code + .replace( + 'require("./"', + `require("${relativePathToBaseDirNormalized}/"` + ) + .replace( + "readFile(join(__dirname", + `readFile(join(__dirname, "${relativePathToBaseDirNormalized}"` + ); + } + ); + }); + }; } const isWebpack5 = true; @@ -48,14 +74,12 @@ const config = { path: false, }; } - useEsbuildMinify(config); + // We need this additional rule to make sure that mjs files are // correctly detected within our src/ folder config.module.rules.push({ test: /\.m?js$/, - // v-- currently using an experimental setting with esbuild-loader - //use: options.defaultLoaders.babel, - use: [{loader: 'esbuild-loader', options: { loader: 'jsx'}}], + use: options.defaultLoaders.babel, exclude: /node_modules/, type: "javascript/auto", resolve: { @@ -64,6 +88,14 @@ const config = { }); config.plugins.push(new ProvidePlugin({ React: "react" })); } + + const ssrPlugin = config.plugins.find( + plugin => plugin instanceof SSRPlugin + ); + + if (ssrPlugin) { + patchSsrPlugin(ssrPlugin); + } return config; }, async redirects() { diff --git a/src/Playground.mjs b/src/Playground.mjs index d551b644e..62a748c43 100644 --- a/src/Playground.mjs +++ b/src/Playground.mjs @@ -1,5 +1,6 @@ // Generated by ReScript, PLEASE EDIT WITH CARE +import * as Eval from "./common/Eval.mjs"; import * as Icon from "./components/Icon.mjs"; import * as Meta from "./components/Meta.mjs"; import * as Next from "./bindings/Next.mjs"; @@ -1422,6 +1423,15 @@ function Playground$Settings(Props) { })))); } +function Playground$Logs(Props) { + var logs = Props.logs; + return React.createElement("ul", undefined, logs.map(function (log, i) { + return React.createElement("li", { + key: i.toString() + }, JSON.stringify(log)); + })); +} + function Playground$ControlPanel$Button(Props) { var children = Props.children; var onClick = Props.onClick; @@ -1499,6 +1509,7 @@ function Playground$ControlPanel(Props) { var state = Props.state; var dispatch = Props.dispatch; var editorCode = Props.editorCode; + var dispatchEval = Props.dispatchEval; var router = Next.Router.useRouter(undefined); var children; var exit = 0; @@ -1529,6 +1540,28 @@ function Playground$ControlPanel(Props) { [Symbol.for("name")]: "Format" }); }; + var onRunClick = function (evt) { + evt.preventDefault(); + var getSuccessCompilationResult = function (result) { + if (result.TAG === /* Success */1) { + return result._0; + } + + }; + var x = ready.result; + if (typeof x === "number") { + console.log("nothing"); + return ; + } + if (x.TAG === /* Conv */0) { + console.log("conv"); + return ; + } + Belt_Option.map(getSuccessCompilationResult(x._0), (function (r) { + return Curry._1(dispatchEval, r.js_code); + })); + + }; var createShareLink = function (param) { var lang = ready.targetLang; var params = lang >= 2 ? [] : [[ @@ -1551,6 +1584,11 @@ function Playground$ControlPanel(Props) { }, React.createElement(Playground$ControlPanel$Button, { children: "Format", onClick: onFormatClick + })), React.createElement("div", { + className: "mr-2" + }, React.createElement(Playground$ControlPanel$Button, { + children: "Run", + onClick: onRunClick })), React.createElement(Playground$ControlPanel$ShareButton, { createShareLink: createShareLink, actionIndicatorKey: actionIndicatorKey @@ -1591,6 +1629,7 @@ function Playground$OutputPanel(Props) { var compilerDispatch = Props.compilerDispatch; var compilerState = Props.compilerState; var editorCode = Props.editorCode; + var evalState = Props.evalState; var prevState = React.useRef(undefined); var prev = prevState.current; var cmCode; @@ -1768,6 +1807,21 @@ function Playground$OutputPanel(Props) { selected = 0; } } + var logs; + if (typeof evalState === "number") { + logs = []; + } else { + switch (evalState.TAG | 0) { + case /* Evaluating */0 : + logs = []; + break; + case /* Evaluated */1 : + case /* Error */2 : + logs = evalState.logs; + break; + + } + } prevSelected.current = selected; var tabs = [ { @@ -1782,6 +1836,12 @@ function Playground$OutputPanel(Props) { } }, errorPane) }, + { + title: "Logs", + content: React.createElement(Playground$Logs, { + logs: logs + }) + }, { title: "Settings", content: React.createElement("div", { @@ -1807,12 +1867,13 @@ var initialResContent = "module Button = {\n @react.component\n let make = (~c function Playground$default(Props) { var router = Next.Router.useRouter(undefined); - var match = Js_dict.get(router.query, "ext"); - var initialLang = match === "re" ? /* Reason */0 : /* Res */2; - var match$1 = Js_dict.get(router.query, "code"); + var match = Eval.useEval(undefined); + var match$1 = Js_dict.get(router.query, "ext"); + var initialLang = match$1 === "re" ? /* Reason */0 : /* Res */2; + var match$2 = Js_dict.get(router.query, "code"); var initialContent; - if (match$1 !== undefined) { - initialContent = LzString.decompressFromEncodedURIComponent(match$1); + if (match$2 !== undefined) { + initialContent = LzString.decompressFromEncodedURIComponent(match$2); } else { switch (initialLang) { case /* Reason */0 : @@ -1825,11 +1886,11 @@ function Playground$default(Props) { } } - var match$2 = React.useState(function () { + var match$3 = React.useState(function () { return 0; }); - var setActionCount = match$2[1]; - var actionCount = match$2[0]; + var setActionCount = match$3[1]; + var actionCount = match$3[0]; var onAction = function (param) { return Curry._1(setActionCount, (function (prev) { if (prev > 1000000) { @@ -1839,32 +1900,32 @@ function Playground$default(Props) { } })); }; - var match$3 = CompilerManagerHook.useCompilerManager(initialLang, onAction, undefined); - var compilerDispatch = match$3[1]; - var compilerState = match$3[0]; + var match$4 = CompilerManagerHook.useCompilerManager(initialLang, onAction, undefined); + var compilerDispatch = match$4[1]; + var compilerState = match$4[0]; var overlayState = React.useState(function () { return false; }); var windowWidth = CodeMirror.useWindowWidth(undefined); - var match$4 = React.useState(function () { + var match$5 = React.useState(function () { }); - var setFocusedRowCol = match$4[1]; + var setFocusedRowCol = match$5[1]; var editorCode = React.useRef(initialContent); if (typeof compilerState !== "number" && compilerState.TAG === /* Ready */2) { var ready = compilerState._0; - var match$5 = ready.result; - if (typeof match$5 === "number") { + var match$6 = ready.result; + if (typeof match$6 === "number") { Curry._1(compilerDispatch, { TAG: 3, _0: ready.targetLang, _1: editorCode.current, [Symbol.for("name")]: "CompileCode" }); - } else if (match$5.TAG === /* Conv */0) { - var match$6 = match$5._0; - if (match$6.TAG === /* Success */0) { - editorCode.current = match$6._0.code; + } else if (match$6.TAG === /* Conv */0) { + var match$7 = match$6._0; + if (match$7.TAG === /* Success */0) { + editorCode.current = match$7._0.code; } } @@ -1897,8 +1958,8 @@ function Playground$default(Props) { if (typeof result === "number") { cmErrors = []; } else if (result.TAG === /* Conv */0) { - var match$7 = result._0; - cmErrors = match$7.TAG === /* Fail */1 ? match$7.details.map(function (param) { + var match$8 = result._0; + cmErrors = match$8.TAG === /* Fail */1 ? match$8.details.map(function (param) { return locMsgToCmError("Error", param); }) : []; } else { @@ -1940,14 +2001,14 @@ function Playground$default(Props) { if (typeof compilerState === "number") { cmHoverHints = []; } else if (compilerState.TAG === /* Ready */2) { - var match$8 = compilerState._0.result; - if (typeof match$8 === "number") { + var match$9 = compilerState._0.result; + if (typeof match$9 === "number") { cmHoverHints = []; - } else if (match$8.TAG === /* Conv */0) { + } else if (match$9.TAG === /* Conv */0) { cmHoverHints = []; } else { - var match$9 = match$8._0; - cmHoverHints = match$9.TAG === /* Success */1 ? match$9._0.type_hints.map(function (hint) { + var match$10 = match$9._0; + cmHoverHints = match$10.TAG === /* Success */1 ? match$10._0.type_hints.map(function (hint) { var start = hint._0.start; var end = hint._0.end; return { @@ -2015,7 +2076,8 @@ function Playground$default(Props) { actionIndicatorKey: String(actionCount), state: compilerState, dispatch: compilerDispatch, - editorCode: editorCode + editorCode: editorCode, + dispatchEval: match[1] }), React.createElement(CodeMirror.make, { errors: cmErrors, hoverHints: cmHoverHints, @@ -2056,7 +2118,8 @@ function Playground$default(Props) { }, React.createElement(Playground$OutputPanel, { compilerDispatch: compilerDispatch, compilerState: compilerState, - editorCode: editorCode + editorCode: editorCode, + evalState: match[0] }), React.createElement("div", { className: "absolute bottom-0 w-full" }, React.createElement(Playground$Statusbar, { diff --git a/src/Playground.res b/src/Playground.res index b5b6f5d9a..4d2325030 100644 --- a/src/Playground.res +++ b/src/Playground.res @@ -1101,6 +1101,18 @@ module Settings = { } } +module Logs = { + @react.component + let make = (~logs) => +