From 1fdd2338f9d71b362816f27530390df92dc95493 Mon Sep 17 00:00:00 2001 From: La Ode Muhammad Al Fatih Date: Wed, 3 Feb 2021 23:17:51 +0700 Subject: [PATCH] chore(examples): update routify version to 2.x --- examples/routify/.gitignore | 11 +- examples/routify/.nolluprc.js | 7 + examples/routify/api/netlify/package.json | 16 + examples/routify/api/netlify/ssr.js | 11 + examples/routify/api/netlify/utils/build.js | 26 + examples/routify/api/vercel-ssr/build.js | 36 + examples/routify/api/vercel-ssr/index.js | 11 + examples/routify/api/vercel-ssr/package.json | 8 + examples/routify/assets/404.svg | 1 + examples/routify/assets/__app.html | 23 + examples/routify/assets/favicon.ico | Bin 0 -> 6518 bytes examples/routify/assets/favicon.png | Bin 0 -> 3127 bytes examples/routify/assets/global.css | 66 + .../assets/images/touch-icons/logo-192.png | Bin 0 -> 8475 bytes .../assets/images/touch-icons/logo-800.png | Bin 0 -> 37271 bytes examples/routify/assets/manifest.json | 21 + .../routify/{static => assets}/robots.txt | 0 examples/routify/netlify.toml | 23 + examples/routify/package.json | 79 +- examples/routify/rollup.config.js | 111 +- examples/routify/sandbox.config.json | 6 + examples/routify/scripts/base.config.js | 98 - examples/routify/src/App.svelte | 8 +- examples/routify/src/Serviceworker.svelte | 19 + examples/routify/src/main.js | 9 +- examples/routify/src/pages/_fallback.svelte | 2 +- examples/routify/src/pages/_layout.svelte | 2 +- examples/routify/src/sw.js | 108 + examples/routify/static/__index.html | 15 - examples/routify/static/favicon.ico | Bin 5430 -> 0 bytes examples/routify/vercel.json | 17 + examples/routify/yarn.lock | 4828 ++++++++--------- 32 files changed, 2859 insertions(+), 2703 deletions(-) create mode 100644 examples/routify/.nolluprc.js create mode 100644 examples/routify/api/netlify/package.json create mode 100644 examples/routify/api/netlify/ssr.js create mode 100644 examples/routify/api/netlify/utils/build.js create mode 100644 examples/routify/api/vercel-ssr/build.js create mode 100644 examples/routify/api/vercel-ssr/index.js create mode 100644 examples/routify/api/vercel-ssr/package.json create mode 100644 examples/routify/assets/404.svg create mode 100644 examples/routify/assets/__app.html create mode 100644 examples/routify/assets/favicon.ico create mode 100644 examples/routify/assets/favicon.png create mode 100644 examples/routify/assets/global.css create mode 100644 examples/routify/assets/images/touch-icons/logo-192.png create mode 100644 examples/routify/assets/images/touch-icons/logo-800.png create mode 100644 examples/routify/assets/manifest.json rename examples/routify/{static => assets}/robots.txt (100%) create mode 100644 examples/routify/netlify.toml create mode 100644 examples/routify/sandbox.config.json delete mode 100644 examples/routify/scripts/base.config.js create mode 100644 examples/routify/src/Serviceworker.svelte create mode 100644 examples/routify/src/sw.js delete mode 100644 examples/routify/static/__index.html delete mode 100644 examples/routify/static/favicon.ico create mode 100644 examples/routify/vercel.json diff --git a/examples/routify/.gitignore b/examples/routify/.gitignore index 1b1141140d..0c2147c3be 100644 --- a/examples/routify/.gitignore +++ b/examples/routify/.gitignore @@ -1,6 +1,9 @@ -/node_modules -/dist +**/node_modules/ +/dist/ .DS_Store +**/.history +src/tmp/ .routify -yarn-debug.log* -yarn-error.log* \ No newline at end of file +.netlify +assets/build +.vercel diff --git a/examples/routify/.nolluprc.js b/examples/routify/.nolluprc.js new file mode 100644 index 0000000000..5a5197fdc9 --- /dev/null +++ b/examples/routify/.nolluprc.js @@ -0,0 +1,7 @@ +module.exports = { + hot: true, + contentBase: 'assets', + publicPath: 'build', + historyApiFallback: '__app.html', + port: 5000 +} diff --git a/examples/routify/api/netlify/package.json b/examples/routify/api/netlify/package.json new file mode 100644 index 0000000000..e11c9fcb11 --- /dev/null +++ b/examples/routify/api/netlify/package.json @@ -0,0 +1,16 @@ +{ + "name": "ssr", + "version": "1.0.0", + "description": "", + "main": "ssr.js", + "scripts": { + "build": "node utils/build.js", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "dependencies": { + "esbuild": "^0.8.8", + "tossr": "^1.3.1" + } +} diff --git a/examples/routify/api/netlify/ssr.js b/examples/routify/api/netlify/ssr.js new file mode 100644 index 0000000000..bef24828c0 --- /dev/null +++ b/examples/routify/api/netlify/ssr.js @@ -0,0 +1,11 @@ +const fs = require('fs') +const { tossr } = require('tossr') +const { script, template } = require('./bundle.json') + +exports.handler = async (event, context) => { + const qs = Object.entries(event.queryStringParameters) + .map(([key, value]) => `${key}=${value}`) + .join('&'); + const body = await tossr(template, script, `${event.path}?${qs}`); + return { statusCode: 200, body: body + '\n' } +} diff --git a/examples/routify/api/netlify/utils/build.js b/examples/routify/api/netlify/utils/build.js new file mode 100644 index 0000000000..4b620a22b8 --- /dev/null +++ b/examples/routify/api/netlify/utils/build.js @@ -0,0 +1,26 @@ +/** + * Creates a JSON and inlines it with esbuild for ssr.js to consume + * { + * data: duh, + * script: inlined main.js + * template: __app.html + * } + */ + +const { resolve } = require('path') +const { readFileSync, writeFileSync } = require('fs') +const { build } = require('esbuild') + +const scriptPath = resolve(__dirname, '../../../dist/build/main.js') +const templatePath = resolve(__dirname, '../../../dist/__app.html') +const bundlePath = resolve(__dirname, '../build/bundle.js') + +build({ entryPoints: [scriptPath], outfile: bundlePath, bundle: true }).then(() => { + const bundle = { + date: new Date, + script: readFileSync(bundlePath, 'utf8'), + template: readFileSync(templatePath, 'utf8') + } + + writeFileSync(resolve(__dirname, '../bundle.json'), JSON.stringify(bundle, null, 2)) +}) diff --git a/examples/routify/api/vercel-ssr/build.js b/examples/routify/api/vercel-ssr/build.js new file mode 100644 index 0000000000..4fd54ba2db --- /dev/null +++ b/examples/routify/api/vercel-ssr/build.js @@ -0,0 +1,36 @@ +const { resolve } = require('path') +const { existsSync } = require('fs') +const { execSync } = require('child_process') +const { rollup } = require('rollup') + +const shouldBuildSpa = process.env.NOW_GITHUB_DEPLOYMENT || process.env.NOW_BUILDER +const script = resolve(__dirname, '../../dist/build/main.js') +const bundlePath = resolve(__dirname, '../../dist/build/bundle.js') + +build() + + +async function build() { + if (shouldBuildSpa) + execSync('npm install && npm run build:app', { cwd: resolve('..', '..'), stdio: 'inherit' }) + else + await waitForAppToExist() + + buildSSRBundle() +} + +async function waitForAppToExist() { + while (!existsSync(script)) { + console.log(`checking if "${script}" exists`) + await new Promise(r => setTimeout(r, 2000)) + } + console.log(`found "${script}"`) +} + +async function buildSSRBundle() { + const bundle = await rollup({ + input: script, + inlineDynamicImports: true, + }) + await bundle.write({ format: 'umd', file: bundlePath, name: 'roxi-ssr' }) +} diff --git a/examples/routify/api/vercel-ssr/index.js b/examples/routify/api/vercel-ssr/index.js new file mode 100644 index 0000000000..1b8afa4fa1 --- /dev/null +++ b/examples/routify/api/vercel-ssr/index.js @@ -0,0 +1,11 @@ +const fs = require('fs') +const { tossr } = require('tossr') + +const script = fs.readFileSync(require.resolve('../../dist/build/bundle.js'), 'utf8') +const template = fs.readFileSync(require.resolve('../../dist/__app.html'), 'utf8') + +module.exports = async (req, res) => { + const html = await tossr(template, script, req.url, {}) + res.send(html + '\n') +} + diff --git a/examples/routify/api/vercel-ssr/package.json b/examples/routify/api/vercel-ssr/package.json new file mode 100644 index 0000000000..16aba092b0 --- /dev/null +++ b/examples/routify/api/vercel-ssr/package.json @@ -0,0 +1,8 @@ +{ + "scripts": { + "vercel-build": "node ./build.js" + }, + "devDependencies": { + "rollup": "^2.28.2" + } +} \ No newline at end of file diff --git a/examples/routify/assets/404.svg b/examples/routify/assets/404.svg new file mode 100644 index 0000000000..1df9552b99 --- /dev/null +++ b/examples/routify/assets/404.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/examples/routify/assets/__app.html b/examples/routify/assets/__app.html new file mode 100644 index 0000000000..100314c9e8 --- /dev/null +++ b/examples/routify/assets/__app.html @@ -0,0 +1,23 @@ + + + + + + + Svelte app + + + + + + + + + + + + + + + + diff --git a/examples/routify/assets/favicon.ico b/examples/routify/assets/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..1708f408ebc7ec2ad46cbcbfad5c3b55fdc33a6b GIT binary patch literal 6518 zcmeHLZA@F&8TQs~kv45grEPzCgX%dQYfbdlUNeKk7eF^LSP0gR}$D}P$ zCspdlnzmXLC2N;8+N5S}=TP%yW4H!`ufJmRVK5kD8!(0d!K6(B{>XXuo@>x3>Vnzu z{xny5bgz%kInR6E^WNuu&s8YCrue$z;6Vl5m5OJ+sZjhxp-?E5o4>!WP*hRdGt@?1 zs7I!qZVCmp|1Z~?6;ERb-^q54xE=>n?NFzC@ta2y3@In`!h@e?J073l#|b@FVF6$V zQiE&~0UXF?JpO^F67S=U^i8Bv|D^FfK(ZTu&T{Ox)-T~LTqDlwz@ra=^ewEX4Xkmu z@yown{_exy<0^X%Nc@q;U18XGkC_r}$U_Hyu-o{#=9NQ{mPIz*JP*G%gpsBRCcWV4 zHRX%Hxbd?ayZRorc*@@x>6khjg{Ni=_DU~oWgZNaxY1eAV=){y|7bTGCY$CCO`Hus z7&|i!PxTm_mBSE=ZLl1-!*JB37YoF1>^6t5KByjgakAcda`3;+^9cHTTXhH{W;63QJN%SdgZgW~H&ZX`A5$7 z)i*zTDTT$Bdx)O9i;yOUiMj~f)xNY;=^3?@I2yM4e%XDdVeRQ<;dAwzu&kyvs3+

gqS9kxj#TS@pt0A zN%(~LT8X!v!2Mt*h`HJO^(#5rk?ueIO* zE%F}z4)OI1!1^ly*?@|`-6>9-DG0~<7Yz{Ju`*j(-X{dY7DNEqs;!o5a&mKsgsE% zHuM}HV8%iV@%O@T%>4FVeEqn-lZ`W8|Jg9})lFgK#YyI=8E5Y5Q4l`{E8MUWzokS% zPtgEO+y@0BYs>FO>oMcS$IYAVfBvShipPMjE{NgUNl*>TT*U9F8iK9jHU`RE%yPnx z-l9Rq_rR#Ku=e~OW;kXF=?`}*v*meQKjOdOs}G4310uzMNHHinPmYMTN>6;CoMN!l z!TDi6Zsj#OYk%I%&lXgh8~05Q{*!&ya@PgUFBVIT^P5zCjAD>tz=T`Rb>%DUWI#?|fpa`7ycdX)p^?)a7tkq)vhl?CmY81QDpxuA&)3qo9oYF31(up-P7 z!ord;(|ku4q!!XafpkDe=U~BC8xZIn6zCi$II4#)+N*}b#7{azF-SVZV_-{%+VZp0 z!aLe~7Zx>ZET&tFWBtK3LyS1xMT!ZBSu!>?PB&%DIX!oq^gFXtjz2QxY(^UFFkEbEZ9%n2TY zvJMsYGt!|wQuFO8ndhGtEng2#YMFjWNzY(Ga0rM7g&%kjX{WK1SzxNEKej zbD^w*axUx->s8{O>#zlFoP4kfnP0ae`#;jWDDT0PhVp+y1adAs!*j78x9OV<>7bko z{~ZHTNK}c+Y~pTbpG_aIdEqX%fz9fcxD9*{7}Wzj2AID-#CR?o`a&-BLe7OJT$eul?ftLTyq){W^Ais| M@xT)gi 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 literal 0 HcmV?d00001 diff --git a/examples/routify/assets/images/touch-icons/logo-800.png b/examples/routify/assets/images/touch-icons/logo-800.png new file mode 100644 index 0000000000000000000000000000000000000000..4247234208f9d98e9d5df6bee993b9b9ced26382 GIT binary patch literal 37271 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

l_tmw` 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 C#ZGYm literal 0 HcmV?d00001 diff --git a/examples/routify/assets/manifest.json b/examples/routify/assets/manifest.json new file mode 100644 index 0000000000..483ba301ba --- /dev/null +++ b/examples/routify/assets/manifest.json @@ -0,0 +1,21 @@ +{ + "background_color": "#ffffff", + "theme_color": "#E938C2", + "name": "Routify app", + "short_name": "Routify app", + "start_url": "/", + "display": "standalone", + "icons": [ + { + "src": "/images/touch-icons/logo-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "/images/touch-icons/logo-800.png", + "sizes": "800x800", + "type": "image/png", + "purpose": "maskable any" + } + ] +} diff --git a/examples/routify/static/robots.txt b/examples/routify/assets/robots.txt similarity index 100% rename from examples/routify/static/robots.txt rename to examples/routify/assets/robots.txt diff --git a/examples/routify/netlify.toml b/examples/routify/netlify.toml new file mode 100644 index 0000000000..9ed12cd620 --- /dev/null +++ b/examples/routify/netlify.toml @@ -0,0 +1,23 @@ + +[build] + publish = "dist" + functions = "api/netlify" + command = "npm run build && cd api/netlify && npm run build" + +# Dev doesn't work yet. Any takers? +# [dev] + # command = "npm run dev:ssr" + # targetPort = 5000 + # publish = "assets" + # autoLaunch = true + +[[redirects]] + # SSR and SPA + from = "/*" + to = "/.netlify/functions/ssr" + status = 200 + + # SPA only + # from = "/*" + # to = "/__app.html" + # status = 200 \ No newline at end of file diff --git a/examples/routify/package.json b/examples/routify/package.json index c40d439528..f1c125bd1e 100644 --- a/examples/routify/package.json +++ b/examples/routify/package.json @@ -1,40 +1,61 @@ { - "version": "0.1.0", - "private": true, + "name": "routify-carbon-app", + "version": "1.0.0", + "@comments scripts": { + "dev": "develop with blazing fast rebuilds", + "dev:features": "develop with features like SSR and serviceworker enabled", + "build": "run build scripts below", + "build:app": "build single page application (SPA)", + "build:static": "Generate static pages", + "serve": "serve content in 'dist' folder", + "rollup": "run the rollup bundler", + "nollup": "run the nollup no-bundler", + "routify": "run routify" + }, "scripts": { - "dev": "run-p dev:*", - "dev:rollup": "rollup -cw", - "dev:routify": "routify", - "build": "routify -b && rollup -c && routify export" + "dev": "run-p routify nollup", + "dev:ssr": "run-p routify rollup", + "build": "run-s build:*", + "build:app": "routify -b && rollup -c", + "build:static": "spank", + "serve": "spassr --ssr", + "rollup": "rollup -cw", + "nollup": "nollup -c", + "routify": "routify" }, "devDependencies": { - "@rollup/plugin-commonjs": "^13.0.0", - "@rollup/plugin-node-resolve": "^8.1.0", - "@rollup/plugin-replace": "^2.3.3", - "@sveltech/routify": "^1.9.1", - "carbon-components-svelte": "^0.12.0", - "marked": "^1.1.1", - "mdsvex": "^0.8.2", - "node-sass": "^4.14.1", + "@rollup/plugin-commonjs": "^15.0.0", + "@rollup/plugin-node-resolve": "^10.0.0", + "@roxi/routify": "^2.8.5", + "carbon-components-svelte": "^0.27.0", + "carbon-icons-svelte": "^10.23.0", + "cross-env": "^7.0.2", + "fs-extra": "^9.0.1", + "nollup": "^0.13.13", "npm-run-all": "^4.1.5", - "remark-slug": "^6.0.0", - "rollup": "^2.18.1", - "rollup-plugin-copy": "^3.3.0", + "postcss": "^8.1.4", + "postcss-import": "^13.0.0", + "rollup": "^2.33.1", + "rollup-plugin-hot": "^0.1.1", + "rollup-plugin-inject-process-env": "^1.3.1", "rollup-plugin-livereload": "^2.0.0", - "rollup-plugin-postcss": "^3.1.8", - "rollup-plugin-svelte": "^5.2.3", - "rollup-plugin-svelte-hot": "^0.9.2", + "rollup-plugin-svelte": "^6.1.0", + "rollup-plugin-svelte-hot": "^0.11.1", "rollup-plugin-terser": "^7.0.2", - "routify-plugin-frontmatter": "^1.0.1", - "spassr": "^1.1.2", - "svelte": "^3.23.2" + "rollup-plugin-workbox": "^5.2.1", + "spank": "^1.5.1", + "spassr": "^2.2.0", + "svelte": "^3.29.4", + "svelte-preprocess": "^4.5.2", + "tossr": "^1.3.1" }, "routify": { - "extensions": "svelte,md", - "routifyDir": ".routify", - "dynamicImports": true, - "plugins": { - "routify-plugin-frontmatter": {} - } + "extensions": "svelte,html,svx,md" + }, + "spassr": {}, + "spank": { + "blacklist": [ + "/example/modal/basic/4" + ] } } diff --git a/examples/routify/rollup.config.js b/examples/routify/rollup.config.js index b11a80b725..5acd152378 100644 --- a/examples/routify/rollup.config.js +++ b/examples/routify/rollup.config.js @@ -1,24 +1,93 @@ -import { createRollupConfigs } from "./scripts/base.config.js"; -import slug from "remark-slug"; -import { mdsvex } from "mdsvex"; +import svelte from 'rollup-plugin-svelte-hot'; +import Hmr from 'rollup-plugin-hot' +import resolve from '@rollup/plugin-node-resolve'; +import commonjs from '@rollup/plugin-commonjs'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import { copySync, removeSync } from 'fs-extra' +import { spassr } from 'spassr' +import getConfig from '@roxi/routify/lib/utils/config' +import autoPreprocess from 'svelte-preprocess' +import postcssImport from 'postcss-import' +import { injectManifest } from 'rollup-plugin-workbox' +import injectProcessEnv from 'rollup-plugin-inject-process-env' + +const { distDir } = getConfig() // use Routify's distDir for SSOT +const assetsDir = 'assets' +const buildDir = `dist/build` +const isNollup = !!process.env.NOLLUP const production = !process.env.ROLLUP_WATCH; -export const config = { - staticDir: "static", - distDir: "dist", - buildDir: "dist/build", - serve: !production, - production, - rollupWrapper: (cfg) => cfg, - svelteWrapper: (svelte) => { - svelte.preprocess = [mdsvex({ remarkPlugins: [slug], extension: "md" })]; - svelte.extensions = [".svelte", ".md"]; - return svelte; - }, - swWrapper: (cfg) => cfg, -}; - -const configs = createRollupConfigs(config); - -export default configs; +// clear previous builds +removeSync(distDir) +removeSync(buildDir) + + +const serve = () => ({ + writeBundle: async () => { + const options = { + assetsDir: [assetsDir, distDir], + entrypoint: `${assetsDir}/__app.html`, + script: `${buildDir}/main.js` + } + spassr({ ...options, port: 5000 }) + spassr({ ...options, ssr: true, port: 5005, ssrOptions: { inlineDynamicImports: true, dev: true } }) + } +}) +const copyToDist = () => ({ writeBundle() { copySync(assetsDir, distDir) } }) + + +export default { + preserveEntrySignatures: false, + input: [`src/main.js`], + output: { + sourcemap: true, + format: 'esm', + dir: buildDir, + // for performance, disabling filename hashing in development + chunkFileNames:`[name]${production && '-[hash]' || ''}.js` + }, + plugins: [ + svelte({ + dev: !production, // run-time checks + // Extract component CSS — better performance + css: css => css.write(`bundle.css`), + hot: isNollup, + preprocess: [ + autoPreprocess({ + postcss: { plugins: [postcssImport()] }, + defaults: { style: 'postcss' } + }) + ] + }), + + // resolve matching modules from current working directory + resolve({ + browser: true, + dedupe: importee => !!importee.match(/svelte(\/|$)/) + }), + commonjs(), + + production && terser(), + !production && !isNollup && serve(), + !production && !isNollup && livereload(distDir), // refresh entire window when code is updated + !production && isNollup && Hmr({ inMemory: true, public: assetsDir, }), // refresh only updated code + injectProcessEnv({ + NODE_ENV: production ? 'production': 'development' + }), + injectManifest({ + globDirectory: assetsDir, + globPatterns: ['**/*.{js,css,svg}', '__app.html'], + swSrc: `src/sw.js`, + swDest: `${distDir}/serviceworker.js`, + maximumFileSizeToCacheInBytes: 10000000, // 10 MB, + mode: 'production' + }), + production && copyToDist(), + ], + watch: { + clearScreen: false, + buildDelay: 100, + } +} diff --git a/examples/routify/sandbox.config.json b/examples/routify/sandbox.config.json new file mode 100644 index 0000000000..5d8e2b1eaf --- /dev/null +++ b/examples/routify/sandbox.config.json @@ -0,0 +1,6 @@ +{ + "container": { + "port": 5000, + "template": "node" + } +} diff --git a/examples/routify/scripts/base.config.js b/examples/routify/scripts/base.config.js deleted file mode 100644 index de4fda8fb5..0000000000 --- a/examples/routify/scripts/base.config.js +++ /dev/null @@ -1,98 +0,0 @@ -import svelte from "rollup-plugin-svelte-hot"; -import resolve from "@rollup/plugin-node-resolve"; -import commonjs from "@rollup/plugin-commonjs"; -import livereload from "rollup-plugin-livereload"; -import { terser } from "rollup-plugin-terser"; -import copy from "rollup-plugin-copy"; -import fs from "fs"; -import replace from "@rollup/plugin-replace"; -import postcss from "rollup-plugin-postcss"; -import { spassr } from "spassr"; -import { version } from "../package.json"; - -export function createRollupConfigs(config) { - const { production, serve, distDir } = config; - const useDynamicImports = process.env.BUNDLING === "dynamic" || !!production; - - fs.rmdirSync(distDir, { recursive: true }); - - if (serve) spassr({ serveSpa: true, serveSsr: true, silent: false }); - - return [ - baseConfig(config, { dynamicImports: false }), - useDynamicImports && baseConfig(config, { dynamicImports: true }), - ].filter(Boolean); -} - -function baseConfig(config, ctx) { - const { dynamicImports } = ctx; - const { - staticDir, - distDir, - production, - buildDir, - svelteWrapper, - rollupWrapper, - } = config; - - const outputConfig = !!dynamicImports - ? { format: "esm", dir: buildDir } - : { format: "iife", file: `${buildDir}/bundle.js` }; - - const svelteConfig = { - dev: !production, - css: (css) => css.write(`${buildDir}/bundle.css`, !production), - hot: false, - }; - - const rollupConfig = { - inlineDynamicImports: !dynamicImports, - input: "src/main.js", - output: { name: "routify_app", sourcemap: !production, ...outputConfig }, - plugins: [ - copy({ - targets: [ - { src: [`${staticDir}/*`, "!*/(__index.html)"], dest: distDir }, - { - src: [`${staticDir}/__index.html`], - dest: distDir, - rename: "__app.html", - transform, - }, - ], - copyOnce: true, - flatten: false, - }), - replace({ "process.env.VERSION": JSON.stringify(version) }), - postcss({ - extract: "bundle.css", - extensions: [".css"], - }), - svelte(svelteWrapper(svelteConfig, ctx)), - resolve({ - browser: true, - dedupe: (importee) => !!importee.match(/svelte(\/|$)/), - }), - commonjs(), - production && terser(), - !production && livereload(distDir), - ], - watch: { - clearScreen: false, - buildDelay: 100, - }, - }; - - return rollupWrapper(rollupConfig, ctx); - - function transform(contents) { - const scriptTag = - typeof config.scriptTag != "undefined" - ? config.scriptTag - : ''; - const bundleTag = ''; - return contents - .toString() - .replace("__SCRIPT__", dynamicImports ? scriptTag : bundleTag); - } -} diff --git a/examples/routify/src/App.svelte b/examples/routify/src/App.svelte index e2d19ce3c6..1e38805542 100644 --- a/examples/routify/src/App.svelte +++ b/examples/routify/src/App.svelte @@ -1,6 +1,10 @@ - + + + \ No newline at end of file diff --git a/examples/routify/src/Serviceworker.svelte b/examples/routify/src/Serviceworker.svelte new file mode 100644 index 0000000000..1392d0a91a --- /dev/null +++ b/examples/routify/src/Serviceworker.svelte @@ -0,0 +1,19 @@ + diff --git a/examples/routify/src/main.js b/examples/routify/src/main.js index 941f6c8ea1..bf553e25ca 100644 --- a/examples/routify/src/main.js +++ b/examples/routify/src/main.js @@ -1,7 +1,6 @@ -import "carbon-components-svelte/css/all.css"; -import HMR from "@sveltech/routify/hmr"; -import App from "./App.svelte"; +import HMR from '@roxi/routify/hmr' +import App from './App.svelte'; -const app = HMR(App, { target: document.body }, "routify-app"); +const app = HMR(App, { target: document.body }, 'routify-carbon-app') -export default app; +export default app; \ No newline at end of file diff --git a/examples/routify/src/pages/_fallback.svelte b/examples/routify/src/pages/_fallback.svelte index f2d685401f..631de87ea1 100644 --- a/examples/routify/src/pages/_fallback.svelte +++ b/examples/routify/src/pages/_fallback.svelte @@ -1,5 +1,5 @@ diff --git a/examples/routify/src/pages/_layout.svelte b/examples/routify/src/pages/_layout.svelte index b3f8d0dc23..eb8af34152 100644 --- a/examples/routify/src/pages/_layout.svelte +++ b/examples/routify/src/pages/_layout.svelte @@ -1,5 +1,5 @@