🔒 SSR UPDATE

This commit is contained in:
NEO 2024-04-21 02:55:19 +08:00
parent 23f82d956a
commit cb44d3db8b
31 changed files with 991 additions and 210 deletions

34
src/entry-client.ts Normal file
View file

@ -0,0 +1,34 @@
// // entry-client.js
// import { createApp } from './main';
//
// const { app, router } = createApp();
//
// router.isReady().then(() => {
// app.mount('#app', true);
// });
// import 'uno.css'; // 确保这是你的 UnoCSS 生成的样式文件
import { createHead } from '@vueuse/head';
// src/entry-client.js
import { createApp } from 'vue';
import { createPinia } from 'pinia';
import App from './App.vue';
import router from '@/router';
import { plausible } from '@/plugins/plausible.plugin';
import { naive } from '@/plugins/naive.plugin';
import { i18nPlugin } from '@/plugins/i18n.plugin';
const app = createApp(App);
const pinia = createPinia();
app.use(pinia);
app.use(createHead());
app.use(i18nPlugin);
app.use(router);
app.use(plausible);
app.use(naive);
router.isReady().then(() => {
app.mount('#app', true);
});

22
src/entry-server.ts Normal file
View file

@ -0,0 +1,22 @@
import { renderToString } from '@vue/server-renderer';
import { setup } from '@css-render/vue3-ssr';
import { createApp } from './main';
// import 'virtual:uno.css';
/**
* Render page with naive ui
*/
export async function render() {
const { app, router, pinia, i18n } = createApp();
const { collect } = setup(app);
const appHtml = await renderToString(app);
const cssHtml = collect();
return {
cssHtml,
appHtml,
app,
router,
pinia,
i18n,
};
}

View file

@ -1,8 +1,8 @@
import { createApp } from 'vue';
import { createSSRApp } from 'vue';
import { createPinia } from 'pinia';
import { createHead } from '@vueuse/head';
import { registerSW } from 'virtual:pwa-register';
// import { registerSW } from 'virtual:pwa-register';
import { plausible } from './plugins/plausible.plugin';
import 'virtual:uno.css';
@ -13,15 +13,28 @@ import App from './App.vue';
import router from './router';
import { i18nPlugin } from './plugins/i18n.plugin';
registerSW();
// registerSW();
const app = createApp(App);
// const app = createApp(App);
app.use(createPinia());
app.use(createHead());
app.use(i18nPlugin);
app.use(router);
app.use(naive);
app.use(plausible);
// app.use(createPinia());
// app.use(createHead());
// app.use(i18nPlugin);
// app.use(router);
// app.use(naive);
// // app.use(plausible);
//
// app.mount('#app');
export function createApp() {
const app = createSSRApp(App);
const pinia = createPinia();
app.use(pinia);
app.use(createHead());
app.use(i18nPlugin);
app.use(router);
app.use(plausible);
app.use(naive);
// 其他插件...
app.mount('#app');
return { app, router, pinia, i18n: i18nPlugin };
}

View file

@ -7,7 +7,7 @@ import type { PaletteOption } from './command-palette.types';
const isModalOpen = ref(false);
const inputRef = ref();
const router = useRouter();
const isMac = computed(() => window.navigator.userAgent.toLowerCase().includes('mac'));
const isMac = computed(() => true);
const commandPaletteStore = useCommandPaletteStore();
const { searchPrompt, filteredSearchResult } = storeToRefs(commandPaletteStore);

View file

@ -1,4 +1,6 @@
<script setup lang="ts">
import CSelect from '@/ui/c-select/c-select.vue';
const { availableLocales, locale } = useI18n();
const localesLong: Record<string, string> = {
@ -21,7 +23,7 @@ const localeOptions = computed(() =>
</script>
<template>
<c-select
<CSelect
v-model:value="locale"
:options="localeOptions"
placeholder="Select a language"

View file

@ -1,5 +1,5 @@
import _ from 'lodash';
import type Plausible from 'plausible-tracker';
// import type Plausible from 'plausible-tracker';
import { inject } from 'vue';
export { createTrackerService, useTracker };
@ -7,21 +7,21 @@ export { createTrackerService, useTracker };
function createTrackerService({ plausible }: { plausible: ReturnType<typeof Plausible> }) {
return {
trackEvent({ eventName }: { eventName: string }) {
plausible.trackEvent(eventName);
// plausible.trackEvent(eventName);
},
};
}
function useTracker() {
const plausible: ReturnType<typeof Plausible> | undefined = inject('plausible');
// const plausible: ReturnType<any> | undefined = inject('plausible');
//
// if (_.isNil(plausible)) {
// throw new TypeError('Plausible must be instantiated');
// }
if (_.isNil(plausible)) {
throw new TypeError('Plausible must be instantiated');
}
const tracker = createTrackerService({ plausible });
// const tracker = createTrackerService({ plausible });
return {
tracker,
tracker: () => {},
};
}

View file

@ -3,18 +3,29 @@ import { get } from '@vueuse/core';
import type { Plugin } from 'vue';
import { createI18n } from 'vue-i18n';
const i18n = createI18n({
legacy: false,
locale: 'en',
messages,
});
// const i18n = createI18n({
// legacy: false,
// locale: 'en',
// messages,
// });
export const i18nPlugin: Plugin = {
install: (app) => {
const i18n = createI18n({
legacy: false,
locale: 'zh',
messages,
});
app.use(i18n);
},
};
export const i18n = createI18n({
legacy: false,
locale: 'zh',
messages,
});
export const translate = function (localeKey: string) {
const hasKey = i18n.global.te(localeKey, get(i18n.global.locale));
return hasKey ? i18n.global.t(localeKey) : localeKey;

View file

@ -1,10 +1,10 @@
import { noop } from 'lodash';
import Plausible from 'plausible-tracker';
// import Plausible from 'plausible-tracker';
import type { App } from 'vue';
import { config } from '@/config';
function createFakePlausibleInstance(): Pick<ReturnType<typeof Plausible>, 'trackEvent' | 'enableAutoPageviews'> {
function createFakePlausibleInstance(): Pick<ReturnType<any>, 'trackEvent' | 'enableAutoPageviews'> {
return {
trackEvent: noop,
enableAutoPageviews: () => noop,
@ -22,7 +22,7 @@ function createPlausibleInstance({
}
}) {
if (config.isTrackerEnabled) {
return Plausible(config);
return config;
}
return createFakePlausibleInstance();

View file

@ -1,4 +1,4 @@
import { createRouter, createWebHistory } from 'vue-router';
import { createMemoryHistory, createRouter } from 'vue-router';
import { layouts } from './layouts/index';
import HomePage from './pages/Home.page.vue';
import NotFound from './pages/404.page.vue';
@ -19,7 +19,7 @@ const toolsRedirectRoutes = tools
);
const router = createRouter({
history: createWebHistory(config.app.baseUrl),
history: createMemoryHistory(config.app.baseUrl),
routes: [
{
path: '/',

View file

@ -12,7 +12,7 @@ import {
sentenceCase,
snakeCase,
} from 'change-case';
import InputCopyable from '../../components/InputCopyable.vue';
import InputCopyable from '@/components/InputCopyable.vue';
const baseConfig = {
stripRegexp: /[^A-Za-zÀ-ÖØ-öø-ÿ]+/gi,

View file

@ -1,7 +1,7 @@
<script setup lang="ts">
import { useThemeVars } from 'naive-ui';
import InputCopyable from '../../components/InputCopyable.vue';
import InputCopyable from '@/components/InputCopyable.vue';
import { computeChmodOctalRepresentation, computeChmodSymbolicRepresentation } from './chmod-calculator.service';
import type { Group, Scope } from './chmod-calculator.types';

View file

@ -2,7 +2,7 @@
import type { lib } from 'crypto-js';
import { MD5, RIPEMD160, SHA1, SHA224, SHA256, SHA3, SHA384, SHA512, enc } from 'crypto-js';
import InputCopyable from '../../components/InputCopyable.vue';
import InputCopyable from '@/components/InputCopyable.vue';
import { convertHexToBin } from './hash-text.service';
import { useQueryParam } from '@/composable/queryParams';

View file

@ -1,4 +1,5 @@
<script setup lang="ts">
import CInputText from "@/ui/c-input-text/c-input-text.vue";
import { extractIBAN, friendlyFormatIBAN, isQRIBAN, validateIBAN } from 'ibantools';
import { getFriendlyErrors } from './iban-validator-and-parser.service';
import type { CKeyValueListItems } from '@/ui/c-key-value-list/c-key-value-list.types';

View file

@ -1,5 +1,5 @@
<script setup lang="ts">
import InputCopyable from '../../components/InputCopyable.vue';
import InputCopyable from '@/components/InputCopyable.vue';
import { convertBase } from './integer-base-converter.model';
import { getErrorMessageIfThrows } from '@/utils/error';

View file

@ -1,7 +1,7 @@
<script setup lang="ts">
import { stringify as stringifyToml } from 'iarna-toml-esm';
import JSON5 from 'json5';
import { withDefaultOnError } from '../../utils/defaults';
import { withDefaultOnError } from '@/utils/defaults';
import type { UseValidationRule } from '@/composable/validation';
const convertJsonToToml = (value: string) => [stringifyToml(JSON5.parse(value))].flat().join('\n').trim();

View file

@ -1,7 +1,7 @@
<script setup lang="ts">
import { useEventListener } from '@vueuse/core';
import InputCopyable from '../../components/InputCopyable.vue';
import InputCopyable from '@/components/InputCopyable.vue';
const event = ref<KeyboardEvent>();

View file

@ -20,7 +20,7 @@ const svgString = computed(() => {
return `
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${w} ${h}"${size}>
<rect width="${w}" height="${h}" fill="${bgColor.value}"></rect>
<text x="50%" y="50%" dominant-baseline="middle" text-anchor="middle" font-family="monospace" font-size="${fontSize.value}px" fill="${fgColor.value}">${text}</text>
<text x="50%" y="50%" dominant-baseline="middle" text-anchor="middle" font-family="monospace" font-size="${fontSize.value}px" fill="${fgColor.value}">${text}</text>
</svg>
`.trim();
});

View file

@ -1,6 +1,6 @@
<script setup lang="ts">
import { parse as parseToml } from 'iarna-toml-esm';
import { withDefaultOnError } from '../../utils/defaults';
import { withDefaultOnError } from '@/utils/defaults';
import { isValidToml } from './toml.services';
import type { UseValidationRule } from '@/composable/validation';

View file

@ -1,5 +1,5 @@
import { parse as parseToml } from 'iarna-toml-esm';
import { isNotThrowing } from '../../utils/boolean';
import { isNotThrowing } from '@/utils/boolean';
export { isValidToml };

View file

@ -1,7 +1,7 @@
<script setup lang="ts">
import { parse as parseToml } from 'iarna-toml-esm';
import { stringify as stringifyToYaml } from 'yaml';
import { withDefaultOnError } from '../../utils/defaults';
import { withDefaultOnError } from '@/utils/defaults';
import { isValidToml } from '../toml-to-json/toml.services';
import type { UseValidationRule } from '@/composable/validation';

View file

@ -1,5 +1,5 @@
<script setup lang="ts">
import InputCopyable from '../../components/InputCopyable.vue';
import InputCopyable from '@/components/InputCopyable.vue';
import { isNotThrowing } from '@/utils/boolean';
import { withDefaultOnError } from '@/utils/defaults';

View file

@ -1,7 +1,7 @@
<script setup lang="ts">
import { stringify as stringifyToml } from 'iarna-toml-esm';
import { parse as parseYaml } from 'yaml';
import { withDefaultOnError } from '../../utils/defaults';
import { withDefaultOnError } from '@/utils/defaults';
import type { UseValidationRule } from '@/composable/validation';
const convertYamlToToml = (value: string) => [stringifyToml(parseYaml(value))].flat().join('\n').trim();

View file

@ -3,6 +3,7 @@ import { useAppTheme } from '../theme/themes';
import type { CLabelProps } from '../c-label/c-label.types';
import type { CSelectOption } from './c-select.types';
import { useTheme } from './c-select.theme';
import CLabel from '@/ui/c-label/c-label.vue';
import { clamp } from '@/modules/shared/number.models';
import { useFuzzySearch } from '@/composable/fuzzySearch';
@ -138,7 +139,7 @@ function onSearchInput() {
</script>
<template>
<c-label v-bind="props">
<CLabel v-bind="props">
<div ref="elementRef" relative class="c-select" w-full>
<div
flex flex-nowrap cursor-pointer items-center
@ -190,7 +191,7 @@ function onSearchInput() {
</div>
</transition>
</div>
</c-label>
</CLabel>
</template>
<style lang="less" scoped>