mirror of
https://github.com/dillonkearns/elm-pages-v3-beta.git
synced 2024-11-28 23:12:22 +03:00
Generate Pages.elm module from a Webpack plugin so it hooks into the lifecycle more smoothly.
This commit is contained in:
parent
701e27953e
commit
cb0f4cbed4
@ -27,10 +27,10 @@ module.exports = class AddFilesPlugin {
|
||||
this.filesToGenerate = filesToGenerate;
|
||||
}
|
||||
apply(/** @type {webpack.Compiler} */ compiler) {
|
||||
compiler.hooks.afterCompile.tapAsync("AddFilesPlugin", (compilation, callback) => {
|
||||
const files = globby
|
||||
.sync(["content/**/*.*"], {})
|
||||
.map(unpackFile);
|
||||
compiler.hooks.emit.tapAsync("AddFilesPlugin", (compilation, callback) => {
|
||||
|
||||
|
||||
const files = globby.sync("content").map(unpackFile);
|
||||
|
||||
|
||||
let staticRequestData = {}
|
||||
@ -53,6 +53,7 @@ module.exports = class AddFilesPlugin {
|
||||
const staticRequests = staticRequestData[route];
|
||||
|
||||
const filename = path.join(file.baseRoute, "content.json");
|
||||
compilation.contextDependencies.add('content')
|
||||
// compilation.fileDependencies.add(filename);
|
||||
compilation.fileDependencies.add(path.resolve(file.filePath));
|
||||
const rawContents = JSON.stringify({
|
||||
|
@ -1,4 +1,4 @@
|
||||
const { compileToString } = require("../node-elm-compiler/index.js");
|
||||
const { compileToStringSync } = require("../node-elm-compiler/index.js");
|
||||
XMLHttpRequest = require("xhr2");
|
||||
|
||||
module.exports = runElm;
|
||||
@ -8,29 +8,29 @@ function runElm(/** @type string */ mode) {
|
||||
const mainElmFile = "../../src/Main.elm";
|
||||
const startingDir = process.cwd();
|
||||
process.chdir(elmBaseDirectory);
|
||||
compileToString([mainElmFile], {}).then(function (data) {
|
||||
(function () {
|
||||
const warnOriginal = console.warn;
|
||||
console.warn = function () { };
|
||||
eval(data.toString());
|
||||
const app = Elm.Main.init({
|
||||
flags: { secrets: process.env, mode, staticHttpCache: global.staticHttpCache }
|
||||
});
|
||||
const data = compileToStringSync([mainElmFile], {});
|
||||
process.chdir(startingDir);
|
||||
(function () {
|
||||
const warnOriginal = console.warn;
|
||||
console.warn = function () { };
|
||||
eval(data.toString());
|
||||
const app = Elm.Main.init({
|
||||
flags: { secrets: process.env, mode, staticHttpCache: global.staticHttpCache }
|
||||
});
|
||||
|
||||
app.ports.toJsPort.subscribe(payload => {
|
||||
process.chdir(startingDir);
|
||||
app.ports.toJsPort.subscribe(payload => {
|
||||
|
||||
if (payload.tag === "Success") {
|
||||
global.staticHttpCache = payload.args[0].staticHttpCache;
|
||||
resolve(payload.args[0])
|
||||
} else {
|
||||
reject(payload.args[0])
|
||||
}
|
||||
delete Elm;
|
||||
console.warn = warnOriginal;
|
||||
});
|
||||
})();
|
||||
|
||||
if (payload.tag === "Success") {
|
||||
global.staticHttpCache = payload.args[0].staticHttpCache;
|
||||
resolve(payload.args[0])
|
||||
} else {
|
||||
reject(payload.args[0])
|
||||
}
|
||||
delete Elm;
|
||||
console.warn = warnOriginal;
|
||||
});
|
||||
})();
|
||||
|
||||
})
|
||||
});
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
const webpack = require("webpack");
|
||||
const middleware = require("webpack-dev-middleware");
|
||||
const path = require("path");
|
||||
const HTMLWebpackPlugin = require("html-webpack-plugin");
|
||||
const ScriptExtHtmlWebpackPlugin = require('script-ext-html-webpack-plugin');
|
||||
@ -15,6 +14,7 @@ const express = require("express");
|
||||
const ClosurePlugin = require("closure-webpack-plugin");
|
||||
const readline = require("readline");
|
||||
const webpackDevMiddleware = require("webpack-dev-middleware");
|
||||
const PluginGenerateElmPagesBuild = require('./plugin-generate-elm-pages-build')
|
||||
|
||||
module.exports = { start, run };
|
||||
function start({ routes, debug, customPort, manifestConfig, routesWithRequests, filesToGenerate }) {
|
||||
@ -384,10 +384,11 @@ function webpackOptions(
|
||||
"./index.js",
|
||||
],
|
||||
plugins: [
|
||||
new PluginGenerateElmPagesBuild(),
|
||||
new webpack.NamedModulesPlugin(),
|
||||
new webpack.HotModuleReplacementPlugin(),
|
||||
// Prevents compilation errors causing the hot loader to lose state
|
||||
// new webpack.NoEmitOnErrorsPlugin(),
|
||||
new webpack.NoEmitOnErrorsPlugin(),
|
||||
],
|
||||
module: {
|
||||
rules: [
|
||||
|
@ -6,7 +6,6 @@ const fs = require("fs");
|
||||
const globby = require("globby");
|
||||
const develop = require("./develop.js");
|
||||
const chokidar = require("chokidar");
|
||||
const doCliStuff = require("./generate-elm-stuff.js");
|
||||
const { elmPagesUiFile } = require("./elm-file-constants.js");
|
||||
const generateRecords = require("./generate-records.js");
|
||||
const parseFrontmatter = require("./frontmatter.js");
|
||||
@ -91,78 +90,91 @@ function run() {
|
||||
const routes = toRoutes(markdownContent);
|
||||
let resolvePageRequests;
|
||||
let rejectPageRequests;
|
||||
global.pagesWithRequests = new Promise(function (resolve, reject) {
|
||||
resolvePageRequests = resolve;
|
||||
rejectPageRequests = reject;
|
||||
|
||||
global.mode = contents.watch ? "dev" : "prod"
|
||||
// global.pagesWithRequests = new Promise(function (resolve, reject) {
|
||||
// resolvePageRequests = resolve;
|
||||
// rejectPageRequests = reject;
|
||||
// });
|
||||
// resolvePageRequests({}); // TODO temporary - do the real resolution
|
||||
|
||||
|
||||
develop.start({
|
||||
routes,
|
||||
debug: contents.debug,
|
||||
manifestConfig: stubManifest,
|
||||
routesWithRequests: {},
|
||||
filesToGenerate: [],
|
||||
customPort: contents.customPort
|
||||
});
|
||||
|
||||
|
||||
doCliStuff(
|
||||
contents.watch ? "dev" : "prod",
|
||||
staticRoutes,
|
||||
markdownContent
|
||||
).then(
|
||||
function (payload) {
|
||||
if (contents.watch) {
|
||||
startWatchIfNeeded();
|
||||
resolvePageRequests(payload.pages);
|
||||
global.filesToGenerate = payload.filesToGenerate;
|
||||
if (!devServerRunning) {
|
||||
devServerRunning = true;
|
||||
develop.start({
|
||||
routes,
|
||||
debug: contents.debug,
|
||||
manifestConfig: payload.manifest,
|
||||
routesWithRequests: payload.pages,
|
||||
filesToGenerate: payload.filesToGenerate,
|
||||
customPort: contents.customPort
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (payload.errors && payload.errors.length > 0) {
|
||||
printErrorsAndExit(payload.errors);
|
||||
}
|
||||
// doCliStuff(
|
||||
// contents.watch ? "dev" : "prod",
|
||||
// staticRoutes,
|
||||
// markdownContent
|
||||
// ).then(
|
||||
// function (payload) {
|
||||
// if (contents.watch) {
|
||||
// startWatchIfNeeded();
|
||||
// resolvePageRequests(payload.pages);
|
||||
// global.filesToGenerate = payload.filesToGenerate;
|
||||
// if (!devServerRunning) {
|
||||
// devServerRunning = true;
|
||||
// develop.start({
|
||||
// routes,
|
||||
// debug: contents.debug,
|
||||
// manifestConfig: payload.manifest,
|
||||
// routesWithRequests: payload.pages,
|
||||
// filesToGenerate: payload.filesToGenerate,
|
||||
// customPort: contents.customPort
|
||||
// });
|
||||
// }
|
||||
// } else {
|
||||
// if (payload.errors && payload.errors.length > 0) {
|
||||
// printErrorsAndExit(payload.errors);
|
||||
// }
|
||||
|
||||
develop.run(
|
||||
{
|
||||
routes,
|
||||
manifestConfig: payload.manifest,
|
||||
routesWithRequests: payload.pages,
|
||||
filesToGenerate: payload.filesToGenerate
|
||||
},
|
||||
() => { }
|
||||
);
|
||||
}
|
||||
// develop.run(
|
||||
// {
|
||||
// routes,
|
||||
// manifestConfig: payload.manifest,
|
||||
// routesWithRequests: payload.pages,
|
||||
// filesToGenerate: payload.filesToGenerate
|
||||
// },
|
||||
// () => { }
|
||||
// );
|
||||
// }
|
||||
|
||||
ensureDirSync("./gen");
|
||||
// ensureDirSync("./gen");
|
||||
|
||||
// prevent compilation errors if migrating from previous elm-pages version
|
||||
deleteIfExists("./gen/Pages/ContentCache.elm");
|
||||
deleteIfExists("./gen/Pages/Platform.elm");
|
||||
// // prevent compilation errors if migrating from previous elm-pages version
|
||||
// deleteIfExists("./gen/Pages/ContentCache.elm");
|
||||
// deleteIfExists("./gen/Pages/Platform.elm");
|
||||
|
||||
fs.writeFileSync(
|
||||
"./gen/Pages.elm",
|
||||
elmPagesUiFile(staticRoutes, markdownContent)
|
||||
);
|
||||
console.log("elm-pages DONE");
|
||||
// fs.writeFileSync(
|
||||
// "./gen/Pages.elm",
|
||||
// elmPagesUiFile(staticRoutes, markdownContent)
|
||||
// );
|
||||
// console.log("elm-pages DONE");
|
||||
|
||||
}
|
||||
).catch(function (errorPayload) {
|
||||
startWatchIfNeeded()
|
||||
resolvePageRequests({ type: 'error', message: errorPayload });
|
||||
if (!devServerRunning) {
|
||||
devServerRunning = true;
|
||||
develop.start({
|
||||
routes,
|
||||
debug: contents.debug,
|
||||
manifestConfig: stubManifest,
|
||||
routesWithRequests: {},
|
||||
filesToGenerate: [],
|
||||
customPort: contents.customPort
|
||||
});
|
||||
}
|
||||
// }
|
||||
// ).catch(function (errorPayload) {
|
||||
// startWatchIfNeeded()
|
||||
// resolvePageRequests({ type: 'error', message: errorPayload });
|
||||
// if (!devServerRunning) {
|
||||
// devServerRunning = true;
|
||||
// develop.start({
|
||||
// routes,
|
||||
// debug: contents.debug,
|
||||
// manifestConfig: stubManifest,
|
||||
// routesWithRequests: {},
|
||||
// filesToGenerate: [],
|
||||
// customPort: contents.customPort
|
||||
// });
|
||||
// }
|
||||
|
||||
});
|
||||
// });
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
const fs = require("fs");
|
||||
const runElm = require("./compile-elm.js");
|
||||
const copyModifiedElmJson = require("./rewrite-elm-json.js");
|
||||
const { elmPagesCliFile } = require("./elm-file-constants.js");
|
||||
const { elmPagesCliFile, elmPagesUiFile } = require("./elm-file-constants.js");
|
||||
const path = require("path");
|
||||
const { ensureDirSync, deleteIfExists } = require('./file-helpers.js')
|
||||
|
||||
@ -19,6 +19,16 @@ module.exports = function run(
|
||||
deleteIfExists("./elm-stuff/elm-pages/Pages/Platform.elm");
|
||||
|
||||
|
||||
const uiFileContent = elmPagesUiFile(staticRoutes, markdownContent)
|
||||
if (global.previousUiFileContent != uiFileContent) {
|
||||
fs.writeFileSync(
|
||||
"./gen/Pages.elm",
|
||||
uiFileContent
|
||||
);
|
||||
}
|
||||
|
||||
global.previousUiFileContent = uiFileContent
|
||||
|
||||
// write `Pages.elm` with cli interface
|
||||
fs.writeFileSync(
|
||||
"./elm-stuff/elm-pages/Pages.elm",
|
||||
|
94
generator/src/plugin-generate-elm-pages-build.js
Normal file
94
generator/src/plugin-generate-elm-pages-build.js
Normal file
@ -0,0 +1,94 @@
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const doCliStuff = require("./generate-elm-stuff.js");
|
||||
const webpack = require('webpack')
|
||||
const parseFrontmatter = require("./frontmatter.js");
|
||||
const generateRecords = require("./generate-records.js");
|
||||
const globby = require("globby");
|
||||
|
||||
module.exports = class PluginGenerateElmPagesBuild {
|
||||
constructor() {
|
||||
this.value = 1;
|
||||
}
|
||||
|
||||
apply(/** @type {webpack.Compiler} */ compiler) {
|
||||
compiler.hooks.afterEmit.tap('DoneMsg', () => {
|
||||
console.log('---> DONE!');
|
||||
|
||||
})
|
||||
|
||||
compiler.hooks.beforeCompile.tap('PluginGenerateElmPagesBuild', (compilation) => {
|
||||
// compiler.hooks.thisCompilation.tap('PluginGenerateElmPagesBuild', (compilation) => {
|
||||
|
||||
// compilation.contextDependencies.add('content')
|
||||
// compiler.hooks.thisCompilation.tap('ThisCompilation', (compilation) => {
|
||||
console.log('----> PluginGenerateElmPagesBuild');
|
||||
const src = `module Example exposing (..)
|
||||
|
||||
value : Int
|
||||
value = ${this.value++}
|
||||
`
|
||||
// console.log('@@@ Writing EXAMPLE module');
|
||||
// fs.writeFileSync(path.join(process.cwd(), './src/Example.elm'), src);
|
||||
|
||||
const staticRoutes = generateRecords();
|
||||
|
||||
const markdownContent = globby
|
||||
.sync(["content/**/*.*"], {})
|
||||
.map(unpackFile)
|
||||
.map(({ path, contents }) => {
|
||||
return parseMarkdown(path, contents);
|
||||
});
|
||||
|
||||
const images = globby
|
||||
.sync("images/**/*", {})
|
||||
.filter(imagePath => !fs.lstatSync(imagePath).isDirectory());
|
||||
|
||||
let resolvePageRequests;
|
||||
let rejectPageRequests;
|
||||
global.pagesWithRequests = new Promise(function (resolve, reject) {
|
||||
resolvePageRequests = resolve;
|
||||
rejectPageRequests = reject;
|
||||
});
|
||||
|
||||
doCliStuff(
|
||||
global.mode,
|
||||
staticRoutes,
|
||||
markdownContent
|
||||
).then((payload) => {
|
||||
console.log('PROMISE RESOLVED doCliStuff');
|
||||
|
||||
|
||||
resolvePageRequests(payload.pages);
|
||||
global.filesToGenerate = payload.filesToGenerate;
|
||||
|
||||
}).catch(function (errorPayload) {
|
||||
resolvePageRequests({ type: 'error', message: errorPayload });
|
||||
})
|
||||
|
||||
|
||||
// compilation.assets['./src/Example.elm'] = {
|
||||
// source: () => src,
|
||||
// size: () => src.length
|
||||
// };
|
||||
// callback()
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
function unpackFile(path) {
|
||||
return { path, contents: fs.readFileSync(path).toString() };
|
||||
}
|
||||
|
||||
function parseMarkdown(path, fileContents) {
|
||||
const { content, data } = parseFrontmatter(path, fileContents);
|
||||
return {
|
||||
path,
|
||||
metadata: JSON.stringify(data),
|
||||
body: content,
|
||||
extension: "md"
|
||||
};
|
||||
}
|
29
index.js
29
index.js
@ -72,6 +72,20 @@ function loadContentAndInitializeApp(/** @type { init: any } */ mainElmModule)
|
||||
});
|
||||
|
||||
|
||||
if (module.hot) {
|
||||
module.hot.addStatusHandler(function (status) {
|
||||
console.log('HMR', status)
|
||||
if (status === 'idle') {
|
||||
|
||||
// httpGet(`${window.location.origin}${path}content.json`).then(function (/** @type JSON */ contentJson) {
|
||||
// // console.log('hot contentJson', contentJson);
|
||||
|
||||
// app.ports.fromJsPort.send({ contentJson: contentJson });
|
||||
// });
|
||||
// console.log('Reloaded!!!!!!!!!!', status)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// found this trick from https://github.com/roots/sage/issues/1826
|
||||
@ -81,18 +95,17 @@ function loadContentAndInitializeApp(/** @type { init: any } */ mainElmModule)
|
||||
const success = reporter.success
|
||||
reporter.success = function () {
|
||||
console.log('SUCCESS');
|
||||
app.ports.fromJsPort.send({});
|
||||
success()
|
||||
}
|
||||
httpGet(`${window.location.origin}${path}content.json`).then(function (/** @type JSON */ contentJson) {
|
||||
// console.log('hot contentJson', contentJson);
|
||||
|
||||
if (module.hot) {
|
||||
module.hot.addStatusHandler(function (status) {
|
||||
if (status === 'idle') {
|
||||
console.log('Reloaded!!!!!!!!!!', status)
|
||||
}
|
||||
setTimeout(() => {
|
||||
app.ports.fromJsPort.send({ contentJson: contentJson });
|
||||
}, 0)
|
||||
success()
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
return app
|
||||
|
||||
});
|
||||
|
@ -223,6 +223,13 @@ type alias ContentJson =
|
||||
}
|
||||
|
||||
|
||||
contentJsonDecoder : Decode.Decoder ContentJson
|
||||
contentJsonDecoder =
|
||||
Decode.map2 ContentJson
|
||||
(Decode.field "body" Decode.string)
|
||||
(Decode.field "staticData" (Decode.dict Decode.string))
|
||||
|
||||
|
||||
init :
|
||||
pathKey
|
||||
-> String
|
||||
@ -272,12 +279,6 @@ init pathKey canonicalSiteUrl document toJsPort viewFn content initUserModel fla
|
||||
|> Decode.decodeValue (Decode.field "contentJson" contentJsonDecoder)
|
||||
|> Result.toMaybe
|
||||
|
||||
contentJsonDecoder : Decode.Decoder ContentJson
|
||||
contentJsonDecoder =
|
||||
Decode.map2 ContentJson
|
||||
(Decode.field "body" Decode.string)
|
||||
(Decode.field "staticData" (Decode.dict Decode.string))
|
||||
|
||||
baseUrl =
|
||||
flags
|
||||
|> Decode.decodeValue (Decode.field "baseUrl" Decode.string)
|
||||
@ -390,7 +391,7 @@ type AppMsg userMsg metadata view
|
||||
| UpdateCacheAndUrl Url (Result Http.Error (ContentCache metadata view))
|
||||
| UpdateCacheForHotReload (Result Http.Error (ContentCache metadata view))
|
||||
| PageScrollComplete
|
||||
| HotReloadComplete
|
||||
| HotReloadComplete ContentJson
|
||||
|
||||
|
||||
type Model userModel userMsg metadata view
|
||||
@ -592,14 +593,19 @@ update content allRoutes canonicalSiteUrl viewFunction pathKey onPageChangeMsg t
|
||||
PageScrollComplete ->
|
||||
( model, Cmd.none )
|
||||
|
||||
HotReloadComplete ->
|
||||
( model
|
||||
, ContentCache.init document content (Maybe.map (\cj -> { contentJson = cj, initialUrl = model.url }) Nothing)
|
||||
|> ContentCache.lazyLoad document
|
||||
{ currentUrl = model.url
|
||||
, baseUrl = model.baseUrl
|
||||
}
|
||||
|> Task.attempt UpdateCacheForHotReload
|
||||
HotReloadComplete contentJson ->
|
||||
let
|
||||
_ =
|
||||
Debug.log "HotReloadComplete" { keys = Dict.keys contentJson.staticData, url = model.url.path }
|
||||
in
|
||||
( { model | contentCache = ContentCache.init document content (Just { contentJson = contentJson, initialUrl = model.url }) }
|
||||
, Cmd.none
|
||||
-- ContentCache.init document content (Maybe.map (\cj -> { contentJson = contentJson, initialUrl = model.url }) Nothing)
|
||||
--|> ContentCache.lazyLoad document
|
||||
-- { currentUrl = model.url
|
||||
-- , baseUrl = model.baseUrl
|
||||
-- }
|
||||
--|> Task.attempt UpdateCacheForHotReload
|
||||
)
|
||||
|
||||
CliMsg _ ->
|
||||
@ -709,7 +715,20 @@ application config =
|
||||
[ config.subscriptions model.userModel
|
||||
|> Sub.map UserMsg
|
||||
|> Sub.map AppMsg
|
||||
, config.fromJsPort |> Sub.map (\_ -> AppMsg HotReloadComplete)
|
||||
, config.fromJsPort
|
||||
|> Sub.map
|
||||
(\decodeValue ->
|
||||
--let
|
||||
-- _ =
|
||||
-- Debug.log "fromJsPort" (decodeValue |> Decode.decodeValue (Decode.field "contentJson" contentJsonDecoder))
|
||||
--in
|
||||
case decodeValue |> Decode.decodeValue (Decode.field "contentJson" contentJsonDecoder) of
|
||||
Ok contentJson ->
|
||||
AppMsg (HotReloadComplete contentJson)
|
||||
|
||||
Err error ->
|
||||
Debug.todo ""
|
||||
)
|
||||
]
|
||||
|
||||
CliModel _ ->
|
||||
|
Loading…
Reference in New Issue
Block a user