start on upgrading sapper

This commit is contained in:
Nolan Lawson 2018-03-18 12:04:09 -07:00
parent 536fa97060
commit 3d6124fcc9
16 changed files with 347 additions and 723 deletions

5
.gitignore vendored
View File

@ -5,4 +5,7 @@ yarn.lock
templates/.*
assets/*.css
/mastodon
mastodon.log
mastodon.log
/app/manifest
/build
/export

View File

@ -1,4 +1,5 @@
import { init } from 'sapper/runtime.js'
import { routes } from './manifest/client.js'
import { loadPolyfills } from '../routes/_utils/loadPolyfills'
import '../routes/_utils/serviceWorkerClient'
import '../routes/_utils/historyEvents'
@ -7,5 +8,9 @@ import '../routes/_utils/loadingMask'
loadPolyfills().then(() => {
console.log('init()')
// `routes` is an array of route objects injected by Sapper
init(document.querySelector('#sapper'), __routes__)
init(document.querySelector('#sapper'), routes)
})
if (module.hot) {
module.hot.accept()
}

View File

@ -1,7 +1,10 @@
const app = require('express')()
const compression = require('compression')
const sapper = require('sapper')
const serveStatic = require('serve-static')
import express from 'express'
import compression from 'compression'
import sapper from 'sapper'
import serveStatic from 'serve-static'
import { routes } from './manifest/server.js'
const app = express()
const { PORT = 4002 } = process.env
@ -16,7 +19,7 @@ app.use(compression({ threshold: 0 }))
app.use(serveStatic('assets'))
app.use(sapper())
app.use(sapper({ routes }))
app.listen(PORT, () => {
console.log(`listening on port ${PORT}`)

View File

@ -1,16 +1,16 @@
const timestamp = '__timestamp__'
import { timestamp, assets, shell, routes } from './manifest/service-worker.js'
const ASSETS = `cache${timestamp}`
// `shell` is an array of all the files generated by webpack,
// `assets` is an array of everything in the `assets` directory
const toCache = __shell__.concat(__assets__)
const toCache = shell.concat(assets)
.filter(filename => !filename.endsWith('.map'))
.filter(filename => !filename.startsWith('apple-icon'))
const cached = new Set(toCache)
// `routes` is an array of `{ pattern: RegExp }` objects that
// match the pages in your app
const routes = __routes__
self.addEventListener('install', event => {
event.waitUntil((async function () {

View File

@ -103,7 +103,7 @@ body.offline,body.theme-hotpants.offline,body.theme-majesty.offline,body.theme-o
</svg><!-- end insert svg here -->
</svg>
<!-- The application will be rendered inside this element,
because `templates/main.js` references it -->
because `templates/client.js` references it -->
<div id='sapper'>%sapper.html%</div>
<!-- Toast.html gets rendered here -->
@ -115,9 +115,9 @@ body.offline,body.theme-hotpants.offline,body.theme-majesty.offline,body.theme-o
<!-- LoadingMask.html gets rendered here -->
<div id="loading-mask" aria-hidden="true"></div>
<!-- Sapper creates a <script> tag containing `templates/main.js`
<!-- Sapper creates a <script> tag containing `templates/client.js`
and anything else it needs to hydrate the app and
initialise the router -->
<script src='%sapper.main%'></script>
%sapper.scripts%
</body>
</html>

View File

@ -16,13 +16,13 @@ const now = require('performance-now')
const globalScss = path.join(__dirname, '../scss/global.scss')
const defaultThemeScss = path.join(__dirname, '../scss/themes/_default.scss')
const offlineThemeScss = path.join(__dirname, '../scss/themes/_offline.scss')
const html2xxFile = path.join(__dirname, '../templates/2xx.html')
const html2xxFile = path.join(__dirname, '../app/template.html')
const scssDir = path.join(__dirname, '../scss')
const themesScssDir = path.join(__dirname, '../scss/themes')
const assetsDir = path.join(__dirname, '../assets')
function doWatch () {
var start = now()
let start = now()
chokidar.watch(scssDir).on('change', debounce(() => {
console.log('Recompiling SCSS...')
Promise.all([

View File

@ -28,7 +28,7 @@ async function main () {
result = `<svg xmlns="http://www.w3.org/2000/svg" style="display:none;">\n${result}\n</svg>`
let html2xxFilepath = path.join(__dirname, '../templates/2xx.html')
let html2xxFilepath = path.join(__dirname, '../app/template.html')
let html2xxFile = await readFile(html2xxFilepath, 'utf8')
html2xxFile = html2xxFile.replace(
/<!-- insert svg here -->[\s\S]+<!-- end insert svg here -->/,

870
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -5,9 +5,9 @@
"scripts": {
"lint": "standard",
"dev": "npm run build-svg && run-p --race build-sass-watch serve",
"serve": "node server.js",
"serve": "PORT=4002 sapper dev",
"build": "npm run globalize-css && npm run build-sass && npm run build-svg && sapper build && npm run deglobalize-css",
"start": "cross-env NODE_ENV=production node server.js",
"start": "PORT=4002 sapper start",
"build-and-start": "run-s build start",
"build-svg": "node ./bin/build-svg.js",
"build-sass": "node ./bin/build-sass.js",
@ -53,7 +53,7 @@
"pify": "^3.0.0",
"quick-lru": "^1.1.0",
"requestidlecallback": "^0.3.0",
"sapper": "nolanlawson/sapper#monkey-patches",
"sapper": "nolanlawson/sapper#ignore-source-maps-built",
"serve-static": "^1.13.1",
"standard": "^10.0.3",
"stringz": "^0.4.0",
@ -116,6 +116,7 @@
"NODE_ENV": "production"
},
"files": [
"app",
"assets",
"bin",
"original-assets",
@ -124,9 +125,7 @@
"templates",
"package.json",
"package-lock.json",
"server.js",
"webpack.client.config.js",
"webpack.server.config.js"
"webpack"
]
}
}

View File

@ -7,7 +7,7 @@
{{#each $loggedInInstancesAsList as instance}}
<SettingsListItem offsetForIcon="{{instance.name !== $currentInstance}}"
icon="{{instance.name === $currentInstance ? '#fa-star' : ''}}"
href="/settings/instances/{{instance.name}}"
href="/settings/instances/list/{{instance.name}}"
label="{{instance.name}}"
ariaLabel="{{instance.name}} {{instance.name === $currentInstance ? '(current instance)' : ''}}" />
{{/each}}

View File

@ -2,36 +2,36 @@
<h1 class="instance-name-h1">{{params.instanceName}}</h1>
{{#if verifyCredentials}}
<h2>Logged in as:</h2>
<div class="acct-current-user">
<Avatar account="{{verifyCredentials}}" className="acct-avatar" size="big"/>
<ExternalLink class="acct-handle"
href="{{verifyCredentials.url}}">
{{'@' + verifyCredentials.acct}}
</ExternalLink>
<span class="acct-display-name">{{verifyCredentials.display_name || verifyCredentials.acct}}</span>
<h2>Logged in as:</h2>
<div class="acct-current-user">
<Avatar account="{{verifyCredentials}}" className="acct-avatar" size="big"/>
<ExternalLink class="acct-handle"
href="{{verifyCredentials.url}}">
{{'@' + verifyCredentials.acct}}
</ExternalLink>
<span class="acct-display-name">{{verifyCredentials.display_name || verifyCredentials.acct}}</span>
</div>
<h2>Theme:</h2>
<form class="theme-chooser" aria-label="Choose a theme">
{{#each themes as theme}}
<div class="theme-group">
<input type="radio" id="choice-theme-{{theme.name}}"
value="{{theme.name}}" checked="$currentTheme === theme.name"
bind:group="selectedTheme" on:change="onThemeChange()">
<label for="choice-theme-{{theme.name}}">{{theme.label}}</label>
</div>
<h2>Theme:</h2>
<form class="theme-chooser" aria-label="Choose a theme">
{{#each themes as theme}}
<div class="theme-group">
<input type="radio" id="choice-theme-{{theme.name}}"
value="{{theme.name}}" checked="$currentTheme === theme.name"
bind:group="selectedTheme" on:change="onThemeChange()">
<label for="choice-theme-{{theme.name}}">{{theme.label}}</label>
</div>
{{/each}}
</form>
{{/each}}
</form>
<form class="instance-actions" aria-label="Switch to or log out of this instance">
{{#if $loggedInInstancesInOrder.length > 1 && $currentInstance !== params.instanceName}}
<button class="primary"
on:click="onSwitchToThisInstance(event)">
Switch to this instance
</button>
{{/if}}
<button on:click="onLogOut(event)">Log out</button>
</form>
<form class="instance-actions" aria-label="Switch to or log out of this instance">
{{#if $loggedInInstancesInOrder.length > 1 && $currentInstance !== params.instanceName}}
<button class="primary"
on:click="onSwitchToThisInstance(event)">
Switch to this instance
</button>
{{/if}}
<button on:click="onLogOut(event)">Log out</button>
</form>
{{/if}}
</SettingsLayout>
<style>
@ -44,8 +44,8 @@
align-items: center;
font-size: 1.3em;
grid-template-areas:
"avatar handle"
"avatar display-name";
"avatar handle"
"avatar display-name";
grid-template-columns: min-content 1fr;
grid-column-gap: 20px;
grid-row-gap: 10px;
@ -91,18 +91,18 @@
}
</style>
<script>
import { store } from '../../../_store/store'
import SettingsLayout from '../../../_components/settings/SettingsLayout.html'
import ExternalLink from '../../../_components/ExternalLink.html'
import Avatar from '../../../_components/Avatar.html'
import { importDialogs } from '../../../_utils/asyncModules'
import { store } from '../../../../_store/store'
import SettingsLayout from '../../../../_components/settings/SettingsLayout.html'
import ExternalLink from '../../../../_components/ExternalLink.html'
import Avatar from '../../../../_components/Avatar.html'
import { importDialogs } from '../../../../_utils/asyncModules'
import {
changeTheme,
switchToInstance,
logOutOfInstance,
updateVerifyCredentialsForInstance
} from '../../../_actions/instances'
import { themes } from '../../../_static/themes'
} from '../../../../_actions/instances'
import { themes } from '../../../../_static/themes'
export default {
components: {

View File

@ -5,9 +5,9 @@
<LazyPage :pageComponent :params />
</Layout>
<script>
import Layout from '../../_components/Layout.html'
import LazyPage from '../../_components/LazyPage.html'
import pageComponent from '../../_pages/settings/instances/[instanceName].html'
import Layout from '../../../_components/Layout.html'
import LazyPage from '../../../_components/LazyPage.html'
import pageComponent from '../../../_pages/settings/instances/list/[instanceName].html'
export default {
components: {

View File

@ -44,7 +44,7 @@ test('Logs in and logs out of localhost:3000', async t => {
.click(settingsButton)
.click($('a').withText('Instances'))
.click($('a').withText('localhost:3000'))
.expect(getUrl()).contains('/settings/instances/localhost:3000')
.expect(getUrl()).contains('/settings/instances/list/localhost:3000')
.expect($('.instance-name-h1').innerText).eql('localhost:3000')
.expect($('.acct-handle').innerText).eql('@foobar')
.expect($('.acct-display-name').innerText).eql('foobar')

View File

@ -3,15 +3,16 @@ const config = require('sapper/webpack/config.js')
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
const LodashModuleReplacementPlugin = require('lodash-webpack-plugin')
const isDev = config.dev
const mode = process.env.NODE_ENV
const isDev = mode === 'development'
module.exports = {
entry: config.client.entry(),
output: config.client.output(),
resolve: {
extensions: ['.js', '.html']
extensions: ['.js', '.json', '.html']
},
mode: isDev ? 'development' : 'production',
mode,
module: {
rules: [
{
@ -21,50 +22,28 @@ module.exports = {
loader: 'svelte-loader',
options: {
hydratable: true,
emitCss: !isDev,
cascade: false,
store: true
store: true,
hotReload: true
}
}
},
isDev && {
test: /\.css$/,
use: [
{ loader: 'style-loader' },
{ loader: 'css-loader' }
]
},
!isDev && {
test: /\.css$/,
/* disable while https://github.com/sveltejs/sapper/issues/79 is open */
/* use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: [{ loader: 'css-loader', options: { sourceMap:isDev } }]
}) */
use: [
{ loader: 'style-loader' },
{ loader: 'css-loader' }
]
}
].filter(Boolean)
]
},
node: {
setImmediate: false
},
plugins: isDev ? [
new webpack.HotModuleReplacementPlugin()
] : [
plugins: [
isDev && new webpack.HotModuleReplacementPlugin(),
new webpack.DefinePlugin({
'process.browser': true,
'process.env.NODE_ENV': '"production"'
'process.env.NODE_ENV': JSON.stringify(mode)
}),
/* disable while https://github.com/sveltejs/sapper/issues/79 is open */
// new ExtractTextPlugin('main.css'),
new LodashModuleReplacementPlugin({
collections: true,
caching: true
}),
new BundleAnalyzerPlugin({ // generates report.html and stats.json
!isDev && new BundleAnalyzerPlugin({ // generates report.html and stats.json
analyzerMode: 'static',
generateStatsFile: true,
statsOptions: {
@ -74,6 +53,6 @@ module.exports = {
openAnalyzer: false,
logLevel: 'silent' // do not bother Webpacker, who runs with --json and parses stdout
})
],
devtool: isDev ? 'cheap-module-source-map' : 'source-map'
].filter(Boolean),
devtool: isDev ? 'inline-source-map' : 'source-map'
}

View File

@ -1,12 +1,14 @@
const config = require('sapper/webpack/config.js')
const pkg = require('../package.json')
module.exports = {
entry: config.server.entry(),
output: config.server.output(),
target: 'node',
resolve: {
extensions: ['.js', '.html']
extensions: ['.js', '.json', '.html']
},
externals: Object.keys(pkg.dependencies),
module: {
rules: [
{
@ -23,5 +25,9 @@ module.exports = {
}
}
]
},
mode: process.env.NODE_ENV,
performance: {
hints: false // it doesn't matter if server.js is large
}
}

View File

@ -0,0 +1,7 @@
const config = require('sapper/webpack/config.js')
module.exports = {
entry: config.serviceworker.entry(),
output: config.serviceworker.output(),
mode: process.env.NODE_ENV
}