perf: use a separate icons.svg file (#1067)
* perf: use a separate icons.svg file This splits icons into inline and non-inline. The inline ones are high priority; the rest go in an icons.svg file. * create SvgIcon.html * determine inlined svgs at build time
This commit is contained in:
parent
2fc6897ee3
commit
880bc7a38a
|
@ -11,6 +11,7 @@ tests
|
|||
/mastodon.log
|
||||
/src/template.html
|
||||
/static/*.css
|
||||
/static/icons.svg
|
||||
/static/robots.txt
|
||||
/static/inline-script.js.map
|
||||
/static/emoji-mart-all.json
|
||||
|
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -5,6 +5,7 @@
|
|||
/mastodon.log
|
||||
/src/template.html
|
||||
/static/*.css
|
||||
/static/icons.svg
|
||||
/static/robots.txt
|
||||
/static/inline-script.js.map
|
||||
/static/emoji-mart-all.json
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
/mastodon.log
|
||||
/src/template.html
|
||||
/static/*.css
|
||||
/static/icons.svg
|
||||
/static/inline-script.js.map
|
||||
/static/emoji-mart-all.json
|
||||
/src/inline-script/checksum.js
|
||||
|
|
|
@ -7,20 +7,32 @@ import $ from 'cheerio'
|
|||
|
||||
const svgo = new SVGO()
|
||||
const readFile = promisify(fs.readFile)
|
||||
const writeFile = promisify(fs.writeFile)
|
||||
|
||||
async function readSvg (svg) {
|
||||
let filepath = path.join(__dirname, '../', svg.src)
|
||||
let content = await readFile(filepath, 'utf8')
|
||||
let optimized = (await svgo.optimize(content))
|
||||
let $optimized = $(optimized.data)
|
||||
let $path = $optimized.find('path').removeAttr('fill')
|
||||
let $symbol = $('<symbol></symbol>')
|
||||
.attr('id', svg.id)
|
||||
.attr('viewBox', `0 0 ${optimized.info.width} ${optimized.info.height}`)
|
||||
.append($path)
|
||||
return $.xml($symbol)
|
||||
}
|
||||
|
||||
export async function buildSvg () {
|
||||
let result = (await Promise.all(svgs.map(async svg => {
|
||||
let filepath = path.join(__dirname, '../', svg.src)
|
||||
let content = await readFile(filepath, 'utf8')
|
||||
let optimized = (await svgo.optimize(content))
|
||||
let $optimized = $(optimized.data)
|
||||
let $path = $optimized.find('path').removeAttr('fill')
|
||||
let $symbol = $('<symbol></symbol>')
|
||||
.attr('id', svg.id)
|
||||
.attr('viewBox', `0 0 ${optimized.info.width} ${optimized.info.height}`)
|
||||
.append($path)
|
||||
return $.xml($symbol)
|
||||
}))).join('\n')
|
||||
let inlineSvgs = svgs.filter(_ => _.inline)
|
||||
let regularSvgs = svgs.filter(_ => !_.inline)
|
||||
|
||||
return `<svg xmlns="http://www.w3.org/2000/svg" style="display:none;">\n${result}\n</svg>`
|
||||
let inlineSvgStrings = (await Promise.all(inlineSvgs.map(readSvg))).join('')
|
||||
let regularSvgStrings = (await Promise.all(regularSvgs.map(readSvg))).join('')
|
||||
|
||||
let inlineOutput = `<svg xmlns="http://www.w3.org/2000/svg" style="display:none">${inlineSvgStrings}</svg>`
|
||||
let regularOutput = `<svg xmlns="http://www.w3.org/2000/svg">${regularSvgStrings}</svg>`
|
||||
|
||||
await writeFile(path.resolve(__dirname, '../static/icons.svg'), regularOutput, 'utf8')
|
||||
|
||||
return inlineOutput
|
||||
}
|
||||
|
|
12
bin/svgs.js
12
bin/svgs.js
|
@ -1,9 +1,9 @@
|
|||
module.exports = [
|
||||
{ id: 'pinafore-logo', src: 'src/static/sailboat.svg' },
|
||||
{ id: 'fa-bell', src: 'src/thirdparty/font-awesome-svg-png/white/svg/bell.svg' },
|
||||
{ id: 'fa-users', src: 'src/thirdparty/font-awesome-svg-png/white/svg/users.svg' },
|
||||
{ id: 'pinafore-logo', src: 'src/static/sailboat.svg', inline: true },
|
||||
{ id: 'fa-bell', src: 'src/thirdparty/font-awesome-svg-png/white/svg/bell.svg', inline: true },
|
||||
{ id: 'fa-users', src: 'src/thirdparty/font-awesome-svg-png/white/svg/users.svg', inline: true },
|
||||
{ id: 'fa-globe', src: 'src/thirdparty/font-awesome-svg-png/white/svg/globe.svg' },
|
||||
{ id: 'fa-gear', src: 'src/thirdparty/font-awesome-svg-png/white/svg/gear.svg' },
|
||||
{ id: 'fa-gear', src: 'src/thirdparty/font-awesome-svg-png/white/svg/gear.svg', inline: true },
|
||||
{ id: 'fa-reply', src: 'src/thirdparty/font-awesome-svg-png/white/svg/reply.svg' },
|
||||
{ id: 'fa-reply-all', src: 'src/thirdparty/font-awesome-svg-png/white/svg/reply-all.svg' },
|
||||
{ id: 'fa-retweet', src: 'src/thirdparty/font-awesome-svg-png/white/svg/retweet.svg' },
|
||||
|
@ -21,8 +21,8 @@ module.exports = [
|
|||
{ id: 'fa-user-times', src: 'src/thirdparty/font-awesome-svg-png/white/svg/user-times.svg' },
|
||||
{ id: 'fa-user-plus', src: 'src/thirdparty/font-awesome-svg-png/white/svg/user-plus.svg' },
|
||||
{ id: 'fa-external-link', src: 'src/thirdparty/font-awesome-svg-png/white/svg/external-link.svg' },
|
||||
{ id: 'fa-search', src: 'src/thirdparty/font-awesome-svg-png/white/svg/search.svg' },
|
||||
{ id: 'fa-comments', src: 'src/thirdparty/font-awesome-svg-png/white/svg/comments.svg' },
|
||||
{ id: 'fa-search', src: 'src/thirdparty/font-awesome-svg-png/white/svg/search.svg', inline: true },
|
||||
{ id: 'fa-comments', src: 'src/thirdparty/font-awesome-svg-png/white/svg/comments.svg', inline: true },
|
||||
{ id: 'fa-paperclip', src: 'src/thirdparty/font-awesome-svg-png/white/svg/paperclip.svg' },
|
||||
{ id: 'fa-thumb-tack', src: 'src/thirdparty/font-awesome-svg-png/white/svg/thumb-tack.svg' },
|
||||
{ id: 'fa-bars', src: 'src/thirdparty/font-awesome-svg-png/white/svg/bars.svg' },
|
||||
|
|
|
@ -5,10 +5,10 @@
|
|||
"scripts": {
|
||||
"lint": "standard && standard --plugin html 'src/routes/**/*.html'",
|
||||
"lint-fix": "standard --fix && standard --fix --plugin html 'src/routes/**/*.html'",
|
||||
"dev": "run-s build-template-html build-third-party-assets serve-dev",
|
||||
"dev": "run-s build-template-html build-assets serve-dev",
|
||||
"serve-dev": "run-p --race build-template-html-watch sapper-dev",
|
||||
"sapper-dev": "cross-env NODE_ENV=development PORT=4002 sapper dev",
|
||||
"before-build": "run-s build-template-html build-third-party-assets",
|
||||
"before-build": "run-s build-template-html build-assets",
|
||||
"build": "cross-env NODE_ENV=production run-s build-steps",
|
||||
"build-steps": "run-s before-build sapper-export build-now-json",
|
||||
"sapper-build": "sapper build",
|
||||
|
@ -16,7 +16,7 @@
|
|||
"build-and-start": "run-s build start",
|
||||
"build-template-html": "node -r esm ./bin/build-template-html.js",
|
||||
"build-template-html-watch": "node -r esm ./bin/build-template-html.js --watch",
|
||||
"build-third-party-assets": "node -r esm ./bin/build-third-party-assets.js",
|
||||
"build-assets": "node -r esm ./bin/build-assets.js",
|
||||
"run-mastodon": "node -r esm ./bin/run-mastodon.js",
|
||||
"test": "cross-env BROWSER=chrome:headless run-s test-browser",
|
||||
"test-browser": "run-p --race run-mastodon build-and-start test-mastodon",
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
{#if error}
|
||||
<svg class={computedClass} style={svgStyle} aria-hidden="true">
|
||||
<use xlink:href="#fa-user" />
|
||||
</svg>
|
||||
<SvgIcon className={computedClass} style={svgStyle} href="#fa-user" />
|
||||
{:elseif $autoplayGifs}
|
||||
<LazyImage
|
||||
className={computedClass}
|
||||
|
@ -37,7 +35,7 @@
|
|||
background: none;
|
||||
}
|
||||
|
||||
svg.avatar {
|
||||
:global(svg.avatar) {
|
||||
fill: var(--deemphasized-text-color);
|
||||
}
|
||||
</style>
|
||||
|
@ -46,6 +44,7 @@
|
|||
import NonAutoplayImg from './NonAutoplayImg.html'
|
||||
import { classname } from '../_utils/classname'
|
||||
import LazyImage from './LazyImage.html'
|
||||
import SvgIcon from './SvgIcon.html'
|
||||
|
||||
export default {
|
||||
data: () => ({
|
||||
|
@ -80,7 +79,8 @@
|
|||
},
|
||||
components: {
|
||||
NonAutoplayImg,
|
||||
LazyImage
|
||||
LazyImage,
|
||||
SvgIcon
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -2,9 +2,7 @@
|
|||
role="navigation" aria-label="Page header"
|
||||
>
|
||||
{#if icon}
|
||||
<svg class="dynamic-page-banner-svg">
|
||||
<use xlink:href={icon} />
|
||||
</svg>
|
||||
<SvgIcon className="dynamic-page-banner-svg" href={icon} />
|
||||
{/if}
|
||||
<h1 class="dynamic-page-title" aria-label={ariaTitle}>{title}</h1>
|
||||
<button type="button"
|
||||
|
@ -24,7 +22,7 @@
|
|||
.dynamic-page-banner.dynamic-page-with-icon {
|
||||
grid-template-columns: min-content 1fr min-content;
|
||||
}
|
||||
.dynamic-page-banner-svg {
|
||||
:global(.dynamic-page-banner-svg) {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
fill: var(--body-text-color);
|
||||
|
@ -64,13 +62,17 @@
|
|||
</style>
|
||||
<script>
|
||||
import Shortcut from './shortcut/Shortcut.html'
|
||||
import SvgIcon from './SvgIcon.html'
|
||||
|
||||
export default {
|
||||
data: () => ({
|
||||
icon: void 0,
|
||||
ariaTitle: ''
|
||||
}),
|
||||
components: { Shortcut },
|
||||
components: {
|
||||
Shortcut,
|
||||
SvgIcon
|
||||
},
|
||||
methods: {
|
||||
onGoBack () {
|
||||
window.history.back()
|
||||
|
|
|
@ -4,27 +4,26 @@
|
|||
aria-label={ariaLabel}
|
||||
class={computedClass}>
|
||||
<slot></slot>{#if showIcon}
|
||||
<svg class="external-link-svg">
|
||||
<use xlink:href="#fa-external-link" />
|
||||
</svg>
|
||||
<SvgIcon className="external-link-svg" href="#fa-external-link" />
|
||||
{/if}</a>
|
||||
<style>
|
||||
.external-link-with-icon {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
}
|
||||
.external-link-with-icon .external-link-svg {
|
||||
:global(.external-link-with-icon .external-link-svg) {
|
||||
margin-left: 4px;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
fill: var(--deemphasized-text-color);
|
||||
}
|
||||
.external-link-with-icon.normal-icon-color .external-link-svg {
|
||||
:global(.external-link-with-icon.normal-icon-color .external-link-svg) {
|
||||
fill: var(--body-text-color);
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
import { classname } from '../_utils/classname'
|
||||
import SvgIcon from './SvgIcon.html'
|
||||
|
||||
export default {
|
||||
data: () => ({
|
||||
|
@ -40,6 +39,9 @@
|
|||
showIcon && 'external-link-with-icon',
|
||||
normalIconColor && 'normal-icon-color'
|
||||
))
|
||||
},
|
||||
components: {
|
||||
SvgIcon
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
@ -7,9 +7,7 @@
|
|||
{disabled}
|
||||
ref:node
|
||||
>
|
||||
<svg class="icon-button-svg {svgClassName || ''}" ref:svg>
|
||||
<use xlink:href={href} />
|
||||
</svg>
|
||||
<SvgIcon className="icon-button-svg {svgClassName || ''}" ref:svg {href} />
|
||||
</button>
|
||||
<style>
|
||||
.icon-button {
|
||||
|
@ -21,14 +19,14 @@
|
|||
justify-content: center;
|
||||
}
|
||||
|
||||
.icon-button-svg {
|
||||
:global(.icon-button-svg) {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
fill: var(--action-button-fill-color);
|
||||
pointer-events: none; /* hack for Edge */
|
||||
}
|
||||
|
||||
.icon-button.big-icon .icon-button-svg {
|
||||
:global(.icon-button.big-icon .icon-button-svg) {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
|
@ -37,24 +35,24 @@
|
|||
* regular styles
|
||||
*/
|
||||
|
||||
.icon-button:hover .icon-button-svg {
|
||||
:global(.icon-button:hover .icon-button-svg) {
|
||||
fill: var(--action-button-fill-color-hover);
|
||||
}
|
||||
|
||||
.icon-button.not-pressable:active .icon-button-svg,
|
||||
.icon-button.same-pressed:active .icon-button-svg {
|
||||
:global(.icon-button.not-pressable:active .icon-button-svg,
|
||||
.icon-button.same-pressed:active .icon-button-svg) {
|
||||
fill: var(--action-button-fill-color-active);
|
||||
}
|
||||
|
||||
.icon-button.pressed.not-same-pressed .icon-button-svg {
|
||||
:global(.icon-button.pressed.not-same-pressed .icon-button-svg) {
|
||||
fill: var(--action-button-fill-color-pressed);
|
||||
}
|
||||
|
||||
.icon-button.pressed.not-same-pressed:hover .icon-button-svg {
|
||||
:global(.icon-button.pressed.not-same-pressed:hover .icon-button-svg) {
|
||||
fill: var(--action-button-fill-color-pressed-hover);
|
||||
}
|
||||
|
||||
.icon-button.pressed.not-same-pressed:active .icon-button-svg {
|
||||
:global(.icon-button.pressed.not-same-pressed:active .icon-button-svg) {
|
||||
fill: var(--action-button-fill-color-pressed-active);
|
||||
}
|
||||
|
||||
|
@ -62,28 +60,28 @@
|
|||
* muted
|
||||
*/
|
||||
|
||||
.icon-button.muted-style .icon-button-svg {
|
||||
:global(.icon-button.muted-style .icon-button-svg) {
|
||||
fill: var(--action-button-deemphasized-fill-color);
|
||||
}
|
||||
|
||||
.icon-button.muted-style:hover .icon-button-svg {
|
||||
:global(.icon-button.muted-style:hover .icon-button-svg) {
|
||||
fill: var(--action-button-deemphasized-fill-color-hover);
|
||||
}
|
||||
|
||||
.icon-button.muted-style.not-pressable:active .icon-button-svg,
|
||||
.icon-button.muted-style.same-pressed:active .icon-button-svg {
|
||||
:global(.icon-button.muted-style.not-pressable:active .icon-button-svg,
|
||||
.icon-button.muted-style.same-pressed:active .icon-button-svg) {
|
||||
fill: var(--action-button-deemphasized-fill-color-active);
|
||||
}
|
||||
|
||||
.icon-button.muted-style.pressed.not-same-pressed .icon-button-svg {
|
||||
:global(.icon-button.muted-style.pressed.not-same-pressed .icon-button-svg) {
|
||||
fill: var(--action-button-deemphasized-fill-color-pressed);
|
||||
}
|
||||
|
||||
.icon-button.muted-style.pressed.not-same-pressed:hover .icon-button-svg {
|
||||
:global(.icon-button.muted-style.pressed.not-same-pressed:hover .icon-button-svg) {
|
||||
fill: var(--action-button-deemphasized-fill-color-pressed-hover);
|
||||
}
|
||||
|
||||
.icon-button.muted-style.pressed.not-same-pressed:active .icon-button-svg {
|
||||
:global(.icon-button.muted-style.pressed.not-same-pressed:active .icon-button-svg) {
|
||||
fill: var(--action-button-deemphasized-fill-color-pressed-active);
|
||||
}
|
||||
|
||||
|
@ -91,7 +89,7 @@
|
|||
<script>
|
||||
import { classname } from '../_utils/classname'
|
||||
import { store } from '../_store/store'
|
||||
import { animate } from '../_utils/animate'
|
||||
import SvgIcon from './SvgIcon.html'
|
||||
|
||||
export default {
|
||||
oncreate () {
|
||||
|
@ -139,16 +137,14 @@
|
|||
},
|
||||
methods: {
|
||||
animate (animation) {
|
||||
let { reduceMotion } = this.store.get()
|
||||
if (!animation || reduceMotion) {
|
||||
return
|
||||
}
|
||||
let svg = this.refs.svg
|
||||
animate(svg, animation)
|
||||
this.refs.svg.animate(animation)
|
||||
},
|
||||
onClick (e) {
|
||||
this.fire('click', e)
|
||||
}
|
||||
},
|
||||
components: {
|
||||
SvgIcon
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,23 +1,27 @@
|
|||
<svg class="loading-spinner-icon spin {maskStyle ? 'mask-style' : ''}"
|
||||
style="width: {size}px; height: {size}px;"
|
||||
aria-label="Loading"
|
||||
>
|
||||
<use xlink:href="#fa-spinner" />
|
||||
</svg>
|
||||
<SvgIcon className="loading-spinner-icon spin {maskStyle ? 'mask-style' : ''}"
|
||||
style="width: {size}px; height: {size}px;"
|
||||
href="#fa-spinner"
|
||||
ariaLabel="Loading"
|
||||
/>
|
||||
<style>
|
||||
.loading-spinner-icon {
|
||||
:global(.loading-spinner-icon) {
|
||||
fill: var(--svg-fill);
|
||||
}
|
||||
|
||||
.loading-spinner-icon.mask-style {
|
||||
:global(.loading-spinner-icon.mask-style) {
|
||||
fill: var(--mask-svg-fill);
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
import SvgIcon from './SvgIcon.html'
|
||||
|
||||
export default {
|
||||
data: () => ({
|
||||
maskStyle: false,
|
||||
size: 64
|
||||
})
|
||||
}),
|
||||
components: {
|
||||
SvgIcon
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
|
Before Width: | Height: | Size: 443 B After Width: | Height: | Size: 543 B |
|
@ -1,16 +1,12 @@
|
|||
{#if showBadge}
|
||||
<div class="nav-link-svg-wrapper">
|
||||
<svg class="nav-link-svg">
|
||||
<use xlink:href={svg} />
|
||||
</svg>
|
||||
<SvgIcon className="nav-link-svg" href={svg} />
|
||||
<span class="nav-link-badge nav-link-badge-digits-{badgeDigits}" aria-hidden="true">
|
||||
{badgeNumberToShow}
|
||||
</span>
|
||||
</div>
|
||||
{:else}
|
||||
<svg class="nav-link-svg">
|
||||
<use xlink:href={svg} />
|
||||
</svg>
|
||||
<SvgIcon className="nav-link-svg" href={svg} />
|
||||
{/if}
|
||||
<style>
|
||||
.nav-link-svg-wrapper {
|
||||
|
@ -18,7 +14,7 @@
|
|||
display: inline-block;
|
||||
}
|
||||
|
||||
.nav-link-svg-wrapper, .nav-link-svg {
|
||||
:global(.nav-link-svg-wrapper, .nav-link-svg) {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
@ -51,7 +47,7 @@
|
|||
font-size: 0.6em;
|
||||
}
|
||||
|
||||
.nav-link-svg {
|
||||
:global(.nav-link-svg) {
|
||||
display: inline-block;
|
||||
fill: var(--nav-svg-fill);
|
||||
}
|
||||
|
@ -61,7 +57,7 @@
|
|||
}
|
||||
|
||||
@media (max-width: 991px) {
|
||||
.nav-link-svg-wrapper, .nav-link-svg {
|
||||
:global(.nav-link-svg-wrapper, .nav-link-svg) {
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
}
|
||||
|
@ -72,6 +68,8 @@
|
|||
}
|
||||
</style>
|
||||
<script>
|
||||
import SvgIcon from './SvgIcon.html'
|
||||
|
||||
export default {
|
||||
data: () => ({
|
||||
showBadge: false,
|
||||
|
@ -80,6 +78,9 @@
|
|||
computed: {
|
||||
badgeDigits: ({ badgeNumber }) => Math.min(3, badgeNumber.toString().length),
|
||||
badgeNumberToShow: ({ badgeNumber }) => (badgeNumber < 100 ? badgeNumber.toString() : '99+')
|
||||
},
|
||||
components: {
|
||||
SvgIcon
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -2,9 +2,7 @@
|
|||
<FreeTextLayout>
|
||||
<div class="not-logged-in-home">
|
||||
<div class="banner">
|
||||
<svg aria-hidden="true" class="not-logged-in-home-svg">
|
||||
<use xlink:href="#pinafore-logo" />
|
||||
</svg>
|
||||
<SvgIcon className="not-logged-in-home-svg" href="#pinafore-logo" />
|
||||
<h1>Pinafore</h1>
|
||||
</div>
|
||||
<p>Pinafore is a web client for <ExternalLink href="https://joinmastodon.org">Mastodon</ExternalLink>, designed for speed and simplicity.</p>
|
||||
|
@ -24,7 +22,7 @@
|
|||
align-items: center;
|
||||
margin: 0 0 30px;
|
||||
}
|
||||
.not-logged-in-home-svg {
|
||||
:global(.not-logged-in-home-svg) {
|
||||
width: 70px;
|
||||
height: 70px;
|
||||
fill: var(--banner-fill);
|
||||
|
@ -47,12 +45,14 @@
|
|||
import FreeTextLayout from './FreeTextLayout.html'
|
||||
import HiddenFromSSR from './HiddenFromSSR.html'
|
||||
import ExternalLink from './ExternalLink.html'
|
||||
import SvgIcon from './SvgIcon.html'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
FreeTextLayout,
|
||||
HiddenFromSSR,
|
||||
ExternalLink
|
||||
ExternalLink,
|
||||
SvgIcon
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
<div class="play-video-icon {className || ''}">
|
||||
<svg class="play-video-icon-svg">
|
||||
<use xlink:href="#fa-play-circle" />
|
||||
</svg>
|
||||
<SvgIcon className="play-video-icon-svg" href="#fa-play-circle" />
|
||||
</div>
|
||||
<style>
|
||||
.play-video-icon {
|
||||
|
@ -16,7 +14,7 @@
|
|||
z-index: 40;
|
||||
pointer-events: none;
|
||||
}
|
||||
.play-video-icon-svg {
|
||||
:global(.play-video-icon-svg) {
|
||||
width: 72px;
|
||||
height: 72px;
|
||||
fill: var(--mask-svg-fill);
|
||||
|
@ -25,9 +23,14 @@
|
|||
}
|
||||
</style>
|
||||
<script>
|
||||
import SvgIcon from './SvgIcon.html'
|
||||
|
||||
export default {
|
||||
data: () => ({
|
||||
className: void 0
|
||||
})
|
||||
}),
|
||||
components: {
|
||||
SvgIcon
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
|
37
src/routes/_components/SvgIcon.html
Normal file
37
src/routes/_components/SvgIcon.html
Normal file
|
@ -0,0 +1,37 @@
|
|||
<svg
|
||||
class={className}
|
||||
{style}
|
||||
aria-hidden={!ariaLabel}
|
||||
aria-label={ariaLabel}
|
||||
ref:svg>
|
||||
<use xlink:href="{inline ? '' : '/icons.svg'}{href}" />
|
||||
</svg>
|
||||
<script>
|
||||
import { animate } from '../_utils/animate'
|
||||
import { store } from '../_store/store'
|
||||
|
||||
export default {
|
||||
data: () => ({
|
||||
className: '',
|
||||
style: '',
|
||||
ariaLabel: ''
|
||||
}),
|
||||
store: () => store,
|
||||
computed: {
|
||||
inline: ({ href }) => {
|
||||
// filled in during build
|
||||
return process.env.INLINE_SVGS.includes(href)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
animate (animation) {
|
||||
let { reduceMotion } = this.store.get()
|
||||
if (!animation || reduceMotion) {
|
||||
return
|
||||
}
|
||||
let svg = this.refs.svg
|
||||
animate(svg, animation)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
After Width: | Height: | Size: 790 B |
|
@ -1,8 +1,6 @@
|
|||
<li class="page-list-item">
|
||||
<a {href} rel="prefetch">
|
||||
<svg class="page-list-item-svg">
|
||||
<use xlink:href={icon} />
|
||||
</svg>
|
||||
<SvgIcon className="page-list-item-svg" href={icon} />
|
||||
<span aria-label={ariaLabel}>
|
||||
{label}
|
||||
</span>
|
||||
|
@ -40,7 +38,7 @@
|
|||
.page-list-item a:active {
|
||||
background: var(--settings-list-item-bg-active);
|
||||
}
|
||||
.page-list-item-svg {
|
||||
:global(.page-list-item-svg) {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
display: inline-block;
|
||||
|
@ -57,7 +55,7 @@
|
|||
.page-list-item a {
|
||||
padding: 20px 10px;
|
||||
}
|
||||
.page-list-item-svg {
|
||||
:global(.page-list-item-svg) {
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
|
@ -66,6 +64,7 @@
|
|||
<script>
|
||||
import { store } from '../../_store/store'
|
||||
import IconButton from '../IconButton'
|
||||
import SvgIcon from '../SvgIcon.html'
|
||||
|
||||
export default {
|
||||
store: () => store,
|
||||
|
@ -82,7 +81,8 @@
|
|||
}
|
||||
},
|
||||
components: {
|
||||
IconButton
|
||||
IconButton,
|
||||
SvgIcon
|
||||
},
|
||||
methods: {
|
||||
onPinClick (e) {
|
||||
|
|
|
@ -8,16 +8,14 @@
|
|||
</span>
|
||||
<div class="compose-box-button-spinner"
|
||||
aria-hidden="true">
|
||||
<svg class="compose-box-button-svg {$postingStatus ? 'spin' : 'hidden'}">
|
||||
<use xlink:href="#fa-spinner" />
|
||||
</svg>
|
||||
<SvgIcon className="compose-box-button-svg {$postingStatus ? 'spin' : 'hidden'}"
|
||||
href="#fa-spinner" />
|
||||
</div>
|
||||
|
||||
<div class="compose-box-button-compose {sticky ? '' : 'hidden'}"
|
||||
aria-hidden="true">
|
||||
<svg class="compose-box-button-svg">
|
||||
<use xlink:href="#fa-pencil" />
|
||||
</svg>
|
||||
<SvgIcon className="compose-box-button-svg"
|
||||
href="#fa-pencil" />
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
|
@ -49,7 +47,7 @@
|
|||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
.compose-box-button-svg {
|
||||
:global(.compose-box-button-svg) {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
fill: var(--button-primary-text);
|
||||
|
@ -65,12 +63,16 @@
|
|||
}
|
||||
</style>
|
||||
<script>
|
||||
import SvgIcon from '../SvgIcon.html'
|
||||
import { store } from '../../_store/store'
|
||||
|
||||
export default {
|
||||
store: () => store,
|
||||
computed: {
|
||||
disabled: ({ $postingStatus, overLimit }) => $postingStatus || overLimit
|
||||
},
|
||||
components: {
|
||||
SvgIcon
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -4,9 +4,7 @@
|
|||
<button class="compose-media-delete-button"
|
||||
aria-label="Delete {shortName}"
|
||||
on:click="onDeleteMedia()" >
|
||||
<svg class="compose-media-delete-button-svg">
|
||||
<use xlink:href="#fa-times" />
|
||||
</svg>
|
||||
<SvgIcon className="compose-media-delete-button-svg" href="#fa-times" />
|
||||
</button>
|
||||
</div>
|
||||
<div class="compose-media-alt">
|
||||
|
@ -73,7 +71,7 @@
|
|||
.compose-media-delete-button:hover {
|
||||
background: var(--toast-border);
|
||||
}
|
||||
.compose-media-delete-button-svg {
|
||||
:global(.compose-media-delete-button-svg) {
|
||||
fill: var(--button-text);
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
|
@ -95,6 +93,7 @@
|
|||
import debounce from 'lodash-es/debounce'
|
||||
import { scheduleIdleTask } from '../../_utils/scheduleIdleTask'
|
||||
import { observe } from 'svelte-extras'
|
||||
import SvgIcon from '../SvgIcon.html'
|
||||
|
||||
export default {
|
||||
oncreate () {
|
||||
|
@ -147,6 +146,9 @@
|
|||
} = this.get()
|
||||
deleteMedia(realm, index)
|
||||
}
|
||||
},
|
||||
components: {
|
||||
SvgIcon
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -2,16 +2,13 @@
|
|||
{#each items as item (item.key)}
|
||||
<li class="generic-dialog-list-item">
|
||||
<button class="generic-dialog-list-button" on:click="fire('click', item)">
|
||||
<svg class="generic-dialog-list-item-svg">
|
||||
<use xlink:href={item.icon} />
|
||||
</svg>
|
||||
<SvgIcon className="generic-dialog-list-item-svg" href={item.icon} />
|
||||
<span class="generic-dialog-list-button-span">
|
||||
{item.label}
|
||||
</span>
|
||||
{#if selectable}
|
||||
<svg class="generic-dialog-list-item-svg {item.selected ? '' : 'hidden'}" aria-hidden={!item.selected}>
|
||||
<use xlink:href="#fa-check" />
|
||||
</svg>
|
||||
<SvgIcon className="generic-dialog-list-item-svg {item.selected ? '' : 'hidden'}"
|
||||
href="#fa-check" />
|
||||
{/if}
|
||||
</button>
|
||||
</li>
|
||||
|
@ -31,7 +28,7 @@
|
|||
font-size: 1.2em;
|
||||
display: flex;
|
||||
}
|
||||
.generic-dialog-list-item-svg {
|
||||
:global(.generic-dialog-list-item-svg) {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
fill: var(--svg-fill);
|
||||
|
@ -88,3 +85,12 @@
|
|||
}
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
import SvgIcon from '../../SvgIcon.html'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
SvgIcon
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -15,9 +15,7 @@
|
|||
<div class="close-dialog-button-wrapper">
|
||||
<button class="close-dialog-button"
|
||||
data-a11y-dialog-hide aria-label="Close dialog">
|
||||
<svg class="close-dialog-button-svg">
|
||||
<use xlink:href="#fa-times" />
|
||||
</svg>
|
||||
<SvgIcon className="close-dialog-button-svg" href="#fa-times" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -102,7 +100,7 @@
|
|||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.close-dialog-button-svg {
|
||||
:global(.close-dialog-button-svg) {
|
||||
padding: 10px;
|
||||
fill: var(--button-primary-text);
|
||||
width: 24px;
|
||||
|
@ -129,7 +127,7 @@
|
|||
.modal-dialog-title {
|
||||
font-size: 1.3em;
|
||||
}
|
||||
.close-dialog-button-svg {
|
||||
:global(.close-dialog-button-svg) {
|
||||
padding: 7px;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
|
@ -138,6 +136,7 @@
|
|||
</style>
|
||||
<script>
|
||||
import Shortcut from '../../shortcut/Shortcut.html'
|
||||
import SvgIcon from '../../SvgIcon.html'
|
||||
import { A11yDialog } from '../../../_thirdparty/a11y-dialog/a11y-dialog'
|
||||
import { classname } from '../../../_utils/classname'
|
||||
import { on, emit } from '../../../_utils/eventBus'
|
||||
|
@ -164,7 +163,7 @@
|
|||
ondestroy () {
|
||||
popShortcutScope('modal')
|
||||
},
|
||||
components: { Shortcut },
|
||||
components: { Shortcut, SvgIcon },
|
||||
data: () => ({
|
||||
// don't animate if we're showing a modal dialog on top of another modal dialog. it looks ugly
|
||||
shouldAnimate: !process.browser || document.getElementsByClassName('modal-dialog').length < 2,
|
||||
|
|
|
@ -19,9 +19,7 @@
|
|||
</div>
|
||||
<div class="account-profile-meta-cell account-profile-meta-verified">
|
||||
{#if field.verified}
|
||||
<svg class="account-profile-meta-verified-svg">
|
||||
<use xlink:href='#fa-check' />
|
||||
</svg>
|
||||
<SvgIcon className="account-profile-meta-verified-svg" href="#fa-check" />
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
|
@ -54,7 +52,7 @@
|
|||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
.account-profile-meta-verified-svg {
|
||||
:global(.account-profile-meta-verified-svg) {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
fill: var(--svg-fill);
|
||||
|
@ -102,6 +100,7 @@
|
|||
}
|
||||
</style>
|
||||
<script>
|
||||
import SvgIcon from '../SvgIcon.html'
|
||||
import { emojifyText } from '../../_utils/emojifyText'
|
||||
import { store } from '../../_store/store'
|
||||
|
||||
|
@ -115,6 +114,9 @@
|
|||
value: emojifyText(field.value, emojis, $autoplayGifs),
|
||||
verified: !!field.verified_at
|
||||
})))
|
||||
},
|
||||
components: {
|
||||
SvgIcon
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
<div class="account-profile-moved-banner">
|
||||
<Avatar className="from-avatar" size="extra-small" {account} />
|
||||
<div class="moved-label">
|
||||
<svg class="moved-svg">
|
||||
<use xlink:href="#fa-suitcase"/>
|
||||
</svg>
|
||||
<SvgIcon className="moved-svg" href="#fa-suitcase" />
|
||||
{accessibleName} has moved:
|
||||
</div>
|
||||
<a class="moved-avatar" href="/accounts/{moved.id}">
|
||||
|
@ -27,7 +25,7 @@
|
|||
grid-area: from-avatar;
|
||||
justify-self: flex-end;
|
||||
}
|
||||
.moved-svg {
|
||||
:global(.moved-svg) {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
fill: var(--deemphasized-text-color);
|
||||
|
@ -64,6 +62,7 @@
|
|||
<script>
|
||||
import { removeEmoji } from '../../_utils/removeEmoji'
|
||||
import Avatar from '../Avatar.html'
|
||||
import SvgIcon from '../SvgIcon.html'
|
||||
|
||||
export default {
|
||||
computed: {
|
||||
|
@ -84,7 +83,8 @@
|
|||
}
|
||||
},
|
||||
components: {
|
||||
Avatar
|
||||
Avatar,
|
||||
SvgIcon
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -8,9 +8,7 @@
|
|||
bind:value="$queryInSearch">
|
||||
</div>
|
||||
<button type="submit" class="primary search-button" aria-label="Search" disabled={$searchLoading}>
|
||||
<svg class="search-button-svg">
|
||||
<use xlink:href="#fa-search" />
|
||||
</svg>
|
||||
<SvgIcon className="search-button-svg" href="#fa-search" />
|
||||
</button>
|
||||
</form>
|
||||
{#if $searchLoading}
|
||||
|
@ -39,7 +37,7 @@
|
|||
border-radius: 10px;
|
||||
flex: 1;
|
||||
}
|
||||
.search-button-svg {
|
||||
:global(.search-button-svg) {
|
||||
fill: var(--button-primary-text);
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
|
@ -60,12 +58,14 @@
|
|||
import LoadingPage from '../LoadingPage.html'
|
||||
import { doSearch } from '../../_actions/search'
|
||||
import SearchResults from './SearchResults.html'
|
||||
import SvgIcon from '../SvgIcon.html'
|
||||
|
||||
export default {
|
||||
store: () => store,
|
||||
components: {
|
||||
LoadingPage,
|
||||
SearchResults
|
||||
SearchResults,
|
||||
SvgIcon
|
||||
},
|
||||
methods: {
|
||||
async onSubmit (e) {
|
||||
|
@ -74,4 +74,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
@ -28,18 +28,14 @@
|
|||
rel="prefetch"
|
||||
href="/statuses/{originalStatusId}/reblogs"
|
||||
aria-label={reblogsLabel}>
|
||||
<svg class="status-favs-reblogs-svg">
|
||||
<use xlink:href="#fa-retweet"/>
|
||||
</svg>
|
||||
<SvgIcon className="status-favs-reblogs-svg" href="#fa-retweet" />
|
||||
<span>{numReblogs}</span>
|
||||
</a>
|
||||
<a class="status-favs-reblogs status-favs"
|
||||
rel="prefetch"
|
||||
href="/statuses/{originalStatusId}/favorites"
|
||||
aria-label={favoritesLabel}>
|
||||
<svg class="status-favs-reblogs-svg">
|
||||
<use xlink:href="#fa-star" />
|
||||
</svg>
|
||||
<SvgIcon className="status-favs-reblogs-svg" href="#fa-star" />
|
||||
<span>{numFavs}</span>
|
||||
</a>
|
||||
</div>
|
||||
|
@ -105,7 +101,7 @@
|
|||
color: var(--deemphasized-text-color);
|
||||
}
|
||||
|
||||
.status-favs-reblogs-svg {
|
||||
:global(.status-favs-reblogs-svg) {
|
||||
fill: var(--deemphasized-text-color);
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
|
@ -137,6 +133,7 @@
|
|||
import ExternalLink from '../ExternalLink.html'
|
||||
import { store } from '../../_store/store'
|
||||
import { absoluteDateFormatter, shortAbsoluteDateFormatter } from '../../_utils/formatters'
|
||||
import SvgIcon from '../SvgIcon.html'
|
||||
import { on } from '../../_utils/eventBus'
|
||||
|
||||
export default {
|
||||
|
@ -191,7 +188,8 @@
|
|||
}
|
||||
},
|
||||
components: {
|
||||
ExternalLink
|
||||
ExternalLink,
|
||||
SvgIcon
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -2,9 +2,7 @@
|
|||
<div class="status-header-avatar {timelineType === 'pinned' ? 'hidden' : ''}">
|
||||
<Avatar {account} size="extra-small"/>
|
||||
</div>
|
||||
<svg class="status-header-svg">
|
||||
<use xlink:href={icon}/>
|
||||
</svg>
|
||||
<SvgIcon className="status-header-svg" href={icon} />
|
||||
|
||||
<div class="status-header-content">
|
||||
{#if timelineType === 'pinned'}
|
||||
|
@ -50,7 +48,7 @@
|
|||
margin-left: 19px; /* offset for avatar, 48px - 24px - 5px */
|
||||
}
|
||||
|
||||
.status-header-svg {
|
||||
:global(.status-header-svg) {
|
||||
min-width: 18px;
|
||||
margin-left: 20px;
|
||||
width: 18px;
|
||||
|
@ -58,7 +56,7 @@
|
|||
fill: var(--deemphasized-text-color);
|
||||
}
|
||||
|
||||
.status-header.status-in-notification .status-header-svg {
|
||||
:global(.status-header.status-in-notification .status-header-svg) {
|
||||
fill: var(--body-text-color);
|
||||
}
|
||||
|
||||
|
@ -98,7 +96,7 @@
|
|||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.status-header-svg {
|
||||
:global(.status-header-svg) {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
|
@ -106,11 +104,13 @@
|
|||
<script>
|
||||
import Avatar from '../Avatar.html'
|
||||
import AccountDisplayName from '../profile/AccountDisplayName.html'
|
||||
import SvgIcon from '../SvgIcon.html'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Avatar,
|
||||
AccountDisplayName
|
||||
AccountDisplayName,
|
||||
SvgIcon
|
||||
},
|
||||
computed: {
|
||||
elementId: ({ uuid }) => `status-header-${uuid}`,
|
||||
|
|
|
@ -7,9 +7,7 @@
|
|||
class="status-sensitive-media-button"
|
||||
aria-label="Hide sensitive media" >
|
||||
<div class="svg-wrapper">
|
||||
<svg class="status-sensitive-media-svg">
|
||||
<use xlink:href="#fa-eye-slash" />
|
||||
</svg>
|
||||
<SvgIcon className="status-sensitive-media-svg" href="#fa-eye-slash" />
|
||||
</div>
|
||||
</button>
|
||||
<MediaAttachments {mediaAttachments} {sensitive} {uuid} />
|
||||
|
@ -23,9 +21,7 @@
|
|||
Sensitive content. Click to show.
|
||||
</div>
|
||||
<div class="svg-wrapper">
|
||||
<svg class="status-sensitive-media-svg">
|
||||
<use xlink:href="#fa-eye" />
|
||||
</svg>
|
||||
<SvgIcon className="status-sensitive-media-svg" href="#fa-eye" />
|
||||
</div>
|
||||
</button>
|
||||
{/if}
|
||||
|
@ -135,7 +131,7 @@
|
|||
.status-sensitive-media-container.status-sensitive-media-shown .svg-wrapper {
|
||||
background: none;
|
||||
}
|
||||
.status-sensitive-media-svg {
|
||||
:global(.status-sensitive-media-svg) {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
fill: var(--mask-svg-fill);
|
||||
|
@ -144,7 +140,7 @@
|
|||
margin: 5px;
|
||||
padding: 6px 10px;
|
||||
}
|
||||
.status-sensitive-media-container.status-sensitive-media-hidden .status-sensitive-media-svg {
|
||||
:global(.status-sensitive-media-container.status-sensitive-media-hidden .status-sensitive-media-svg) {
|
||||
fill: var(--deemphasized-text-color);
|
||||
background: var(--mask-opaque-bg);
|
||||
}
|
||||
|
@ -152,6 +148,7 @@
|
|||
<script>
|
||||
import MediaAttachments from './MediaAttachments.html'
|
||||
import Shortcut from '../shortcut/Shortcut.html'
|
||||
import SvgIcon from '../SvgIcon.html'
|
||||
import { store } from '../../_store/store'
|
||||
import { registerClickDelegate } from '../../_utils/delegate'
|
||||
import { classname } from '../../_utils/classname'
|
||||
|
@ -163,7 +160,8 @@
|
|||
},
|
||||
components: {
|
||||
MediaAttachments,
|
||||
Shortcut
|
||||
Shortcut,
|
||||
SvgIcon
|
||||
},
|
||||
store: () => store,
|
||||
computed: {
|
||||
|
|
|
@ -16,9 +16,8 @@
|
|||
title={instance.switchLabel}
|
||||
aria-pressed={instance.current}
|
||||
on:click="onSwitchToThisInstance(event, instance.name)">
|
||||
<svg class="instance-switcher-button-svg">
|
||||
<use xlink:href="{instance.current ? '#fa-star' : '#fa-star-o'}" />
|
||||
</svg>
|
||||
<SvgIcon className="instance-switcher-button-svg"
|
||||
href={instance.current ? '#fa-star' : '#fa-star-o'} />
|
||||
</button>
|
||||
</div>
|
||||
</SettingsListRow>
|
||||
|
@ -55,7 +54,7 @@
|
|||
justify-content: center;
|
||||
margin: 1px;
|
||||
}
|
||||
.instance-switcher-button-svg {
|
||||
:global(.instance-switcher-button-svg) {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
display: inline-block;
|
||||
|
@ -69,13 +68,15 @@
|
|||
import SettingsList from '../../../_components/settings/SettingsList.html'
|
||||
import SettingsListRow from '../../../_components/settings/SettingsListRow.html'
|
||||
import SettingsListButton from '../../../_components/settings/SettingsListButton.html'
|
||||
import SvgIcon from '../../../_components/SvgIcon.html'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
SettingsLayout,
|
||||
SettingsList,
|
||||
SettingsListRow,
|
||||
SettingsListButton
|
||||
SettingsListButton,
|
||||
SvgIcon
|
||||
},
|
||||
methods: {
|
||||
onSwitchToThisInstance (e, instanceName) {
|
||||
|
|
|
@ -4,7 +4,7 @@ const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPl
|
|||
const LodashModuleReplacementPlugin = require('lodash-webpack-plugin')
|
||||
const terser = require('./terser.config')
|
||||
const CircularDependencyPlugin = require('circular-dependency-plugin')
|
||||
const { mode, dev, resolve } = require('./shared.config')
|
||||
const { mode, dev, resolve, inlineSvgs } = require('./shared.config')
|
||||
|
||||
const output = Object.assign(config.client.output(), {
|
||||
// enables HMR in workers
|
||||
|
@ -51,6 +51,11 @@ module.exports = {
|
|||
}
|
||||
},
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
'process.browser': true,
|
||||
'process.env.NODE_ENV': JSON.stringify(mode),
|
||||
'process.env.INLINE_SVGS': JSON.stringify(inlineSvgs)
|
||||
}),
|
||||
new webpack.NormalModuleReplacementPlugin(
|
||||
/\/_database\/database\.js$/, // this version plays nicer with IDEs
|
||||
'./database.prod.js'
|
||||
|
@ -66,10 +71,6 @@ module.exports = {
|
|||
requestTimeout: 120000
|
||||
})
|
||||
] : [
|
||||
new webpack.DefinePlugin({
|
||||
'process.browser': true,
|
||||
'process.env.NODE_ENV': JSON.stringify(mode)
|
||||
}),
|
||||
new BundleAnalyzerPlugin({ // generates report.html and stats.json
|
||||
analyzerMode: 'static',
|
||||
generateStatsFile: true,
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
const webpack = require('webpack')
|
||||
const config = require('sapper/config/webpack.js')
|
||||
const pkg = require('../package.json')
|
||||
const { mode, dev, resolve } = require('./shared.config')
|
||||
const { mode, dev, resolve, inlineSvgs } = require('./shared.config')
|
||||
|
||||
module.exports = {
|
||||
entry: config.server.entry(),
|
||||
|
@ -28,5 +29,10 @@ module.exports = {
|
|||
mode,
|
||||
performance: {
|
||||
hints: false // it doesn't matter if server.js is large
|
||||
}
|
||||
},
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
'process.env.INLINE_SVGS': JSON.stringify(inlineSvgs)
|
||||
})
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
const mode = process.env.NODE_ENV
|
||||
const svgs = require('../bin/svgs')
|
||||
|
||||
const inlineSvgs = svgs.filter(_ => _.inline).map(_ => `#${_.id}`)
|
||||
const mode = process.env.NODE_ENV || 'production'
|
||||
const dev = mode === 'development'
|
||||
|
||||
const resolve = {
|
||||
|
@ -14,5 +17,6 @@ const resolve = {
|
|||
module.exports = {
|
||||
mode,
|
||||
dev,
|
||||
resolve
|
||||
resolve,
|
||||
inlineSvgs
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue