为什么选择插件vite-ssg + vite-plugin-pages创建官网?
适合高度动态的 Web 应用程序
客户端渲染 CSR. : 典型代表:单页面应用,内容都是js动态渲染
服务器端渲染 SSR : 在服务端获取数据组装页面,返回到浏览器是html,对服务器要求高,主要应用是交互多的页面需要seo的
适合高度静态的web程序
静态站点生成 SSG: 在build的的时候就已经生成好静态页面,放在服务端的也是静态页面,博客,静态官网都非常合适
增量静态再生 ISR:ISR 是 SSG 的下一个改进,它定期构建和重新验证新页面,以便内容永远不会过时
显而易见,做个官网ssg就非常合适,正好相关插件vite-ssg也有,配合多页面插件vite-plugin-pages来尝试一下
npm create vite@latest
yarn create vite
pnpm create vite
按照命令提示写项目名称,我选择vue-ts作为项目就可以生成项目了
vite-ssg 需要vue-router 和 @vueuse/head
yarn add vite-plugin-pages vite-ssg vue-router @vueuse/head vite-plugin-md -D
vite-plugin-md 该插件支持使用makdown语法转换为vue
支持在vue文件中直接引入md文件组件,也可以在md文件中直接使用vue组件
需要配置
ViteVue({
include: [/\.vue$/, /\.md$/],
})
修改main.ts
import './style.css'
import App from './App.vue'
import { ViteSSG } from 'vite-ssg'
import routes from '~pages'
export const createApp = ViteSSG(
App,
{ routes }
);
如果~pages有提示找不到模块或相应的类型声明,其实文档中已有说明
在vite-env.d.ts中加入声明
// vite-env.d.ts
/// <reference types="vite-plugin-pages/client" />
同理在tsconfig.json中加入也是一样的,两个地方选择一个加入就可以
"compilerOptions": {
"types": [
"vite-plugin-pages/client"
],
},
修改build脚本
- "build": "vite build"
+ "build": "vite-ssg build"
修改vite.config.ts
import { defineConfig } from "vite";
import ViteVue from "@vitejs/plugin-vue";
import VitePages from 'vite-plugin-pages';
import ViteMarkdown from 'vite-plugin-md';
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
export default defineConfig({
plugins: [
ViteVue({
include: [/\.vue$/, /\.md$/],
}),
VitePages({
extensions: ['vue', 'md'],
exclude: ['**/components/*.vue']
}),
ViteMarkdown(),
AutoImport({
imports: ['vue']
}),
Components({
extensions: ['vue', 'md']
}),
],
});
修改app.vue
<template>
<router-view />
</template>
vite-plugin-pages的配置项来新建文件夹主要看以下几个配置项
interface Options {
/**
* Paths to the directory to search for page components.
* @default 'src/pages'
*/
dirs: string | (string | PageOptions)[];
/**
* Valid file extensions for page components.
* @default ['vue', 'js']
*/
extensions: string[];
/**
* List of path globs to exclude when resolving pages.
*/
exclude: string[];
/**
* Extend route records
*/
extendRoute?: (route: any, parent: any | undefined) => any | void;
}
dirs 默认是src/pages, 这就是我们新建页面的地方。
extensions默认是['vue', 'js'] 在src/pages中默认可以转换成页面的文件类型,这里我们将vue文件和md文件转换就可以了,配置为extensions: ['vue', 'md']
extendRoute通过这个配置可以为路由信息增加额外信息,自由发挥
exclude 可以排除某些vue文件不生成页面。比如我的页面中有组件: exclude: ['**/components/*.vue']
tip:文档中提到一个匹配所有404路由的方式:新建一个[...all].vue文件即可。
src/pages/[...all].vue -> /* (/non-existent-page)

可以发现
src/pages/index.vue
可以选择性观察本篇vite + vue3 多页面实战优化续集:eslint+lint-staged+husky+stylelint
官网有新的一行命令生成eslint: npm init @eslint/config可以替代 npx eslint --init,
同样的一步步往下选择
上述文章中安装eslint非常顺利,这次配置eslint出现了不少错误提示.可以发现与上次安装插件相比的eslint-config-standard 变成了eslint-config-standard-with-typescript
"@typescript-eslint/eslint-plugin": "^5.44.0",
"eslint": "^8.28.0",
"eslint-config-standard-with-typescript": "^23.0.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-n": "^15.5.1",
"eslint-plugin-promise": "^6.1.1",
"eslint-plugin-vue": "^9.8.0",
有变化就要踩坑,从插件名称上看是主要针对ts的写法校验,这里记录一下这次出现的问题:
starkoverflow有提到要在.eslintrc 中加入project
parserOptions: {
project: ['./tsconfig.json'],
extraFileExtensions: ['.vue']
}
.vue) is non-standard. You should add parserOptions.extraFileExtensions to your config。 如上述配置加入extraFileExtensions: ['.vue']
strictNullChecks compiler option to be turned on to function correctly @typescript-eslint/strict-boolean-expressions可以在.eslintrc 的rules中设置为警告,并在tsconfig.json中开启"strictNullChecks": true,修改tsconfig.json记得重启项目生效 starkoverflow
// .eslintrc
rules: {
"@typescript-eslint/strict-boolean-expressions": "warn",
}
// tsconfig.json
"compilerOptions": {
"strictNullChecks": true
}
以前的null严格检查为了向下兼容都是默认关闭的,现在新建项目建议都开启null检查,可以避免很多空值导致的bug
如果你不想用它,也可以直接设为关闭:‘off’
关于问题二三我在eslint官网也看到了相关配置
{
"root": true,
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended"
],
"parser": "@typescript-eslint/parser",
"parserOptions": { "project": ["./tsconfig.json"] },
"plugins": [
"@typescript-eslint"
],
"rules": {
"@typescript-eslint/strict-boolean-expressions": [
2,
{
"allowString" : false,
"allowNumber" : false
}
]
},
"ignorePatterns": ["src/**/*.test.ts", "src/frontend/generated/*"]
}
import style instead @typescript-eslint/triple-slash-reference不鼓励使用三斜线,在vite-env.d.ts中有vite/client类型引入。关掉这个规则吧
// .eslintrc
rules: {
'@typescript-eslint/triple-slash-reference': 'off'
}
.eslintrc.cjs中的module.exports飘红:However, that TSConfig does not include this file. Either:tsconfig.json不包含本文件那就在tsconfig.json的include数组中加入.eslintrc.cjs.重启生效
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue",".eslintrc.cjs"],

加入parser解决,这里的@typescript-eslint/parser就不需要单独安装了。
eslint-config-standard-with-typescript文档中说了
This package has @typescript-eslint/parser in dependencies.
parserOptions: {
parser: '@typescript-eslint/parser',
}
原因:我的vscode在设置中的用户开启了format on save,这是针对我的编辑器。
此时我还没在项目中新建针对工作区的.vscode/settings.json文件。所以此时保存自动格式化的能力完全来源于用户中的format on save
解决:
用户中的format on save,关闭后任何文件保存就不会自动格式化了.vscode/settings.json文件,加入以下配置就会修改每个人的工作区配置,达到项目配置的统一了"editor.codeActionsOnSave": {
"source.fixAll.eslint": true,
"source.fixAll.tslint": true,
"source.fixAll.stylelint": true
}
直接修改工作区配置,在.vscode/settings.json中加入
关闭编辑器的格式化,按照eslint的规则来
{
"editor.formatOnSave": false,
}
当然你也可以选择性加入使用prettier,我这里稍微写一下(以下prettier内容可以跳过)
这里使用prettier 集成到 eslint 的校验中
第一步新建json文件
echo {}> .prettierrc.json
// .prettierrc.json
{
"semi": false,
"singleQuote": true,
"trailingComma": "none"
}
prettier 冲突的规则prettier 代替 eslint 格式化第二步安装
npm i prettier eslint-config-prettier eslint-plugin-prettier -D
第三步:在 .eslintrc.cjs 三个地方 加入prettier.
module.exports = {
extends: [
'plugin:vue/vue3-essential',
'standard-with-typescript',
'prettier'
],
plugins: [
'vue',
'@typescript-eslint',
'prettier'
],
rules: {
'prettier/prettier': 'error',
}
}
unplugin-auto-import自动导入,但是eslint会检测Cannot find name ‘ref’
解决:
vite.config.ts的unplugin-auto-import/vite配置项中加入eslintrc.enabled 开启为truenpm run dev 运行项目,此时项目根目录会自动生成.eslintrc-auto-import.json文件eslintrc.cjs 的extends加入该文件eslintrc.enabled,避免重复生成// eslintrc.cjs
extends: [
'plugin:vue/vue3-essential',
'standard-with-typescript',
'prettier',
'./.eslintrc-auto-import.json'
]
// vite.config.ts
import AutoImport from 'unplugin-auto-import/vite'
export default defineConfig({
AutoImport({
imports: ['vue', 'vue-router'],
eslintrc: {
enabled: true
}
}),
})
vscode提示报错,less文件也没有正常校验。其实上面说的很明确了,本次新建的项目package.json中默认有"type": "module",这种情况下,我们平常新建的.stylelintrc.js或者.eslintrc.js 里面都是使用的module.exports,和定义"type": "module"完全使用es模块的import方式是不兼容的。
解决:将.stylelintrc.js改为.stylelintrc.cjs,用后缀名使其识别为commonjs方式导出,修改后less文件不规范的地方也被正常识别红色波浪了
2023年1月12新增: 在项目使用过程中发现新的配置问题
vite-ssg的github项目issue中问的最多的就是打包的时候报错:"window is not defined","document is not defined" .打包是在服务器,是没有BOM浏览器相关的东西的。所以在使用window的时候,我们分两种情况来使用
ViteSSG第三个参数函数中的isClient来判断是否是浏览器中。npm vite-ssg还有详细的案例告诉我们vuex和initialState来保持数据持久的方式export const createApp = ViteSSG(App, { routes }, ({ app, router, routes, isClient, initialState }) => {
// app.provide('$wow', WOW)
if (isClient) {
window.onload = fontSize()
}
})
onBeforeMount,onMounted生命周期中export default function () {
const isMobile = ref(false)
const resizeHandler = () => {
if (!document.hidden) {
const rect = document.body.getBoundingClientRect()
isMobile.value = rect.width - 1 < 750
}
}
onMounted(() => {
resizeHandler()
window.addEventListener('resize', resizeHandler)
})
onBeforeUnmount(() => {
window.removeEventListener('resize', resizeHandler)
})
return { isMobile }
}
export const install = ({ isClient, app }) => {
if (isClient)
import('vue3-scroll-spy').then(({ registerScrollSpy }) => {
registerScrollSpy(app)
})
}
// 你要说想在单个页面引入,那就在onMounted中
onMounted(() => {
import('vue3-scroll-spy').then(({ registerScrollSpy }) => {
registerScrollSpy(app)
})
})
先安装
npm i animate.css wowjs
main.ts引入
import 'animate.css/animate.min.css'. // 这是
import { WOW } from 'wowjs'
new WOW({
boxClass: 'wow', //需要执行动画元素的Class
animateClass: 'animated', //animation.css动画的Class
offset: 0, //距离可视区域多少开始执行动画
mobile: true, //是否在移动设备执行动画
live: true //异步加载的内容是否有效
}).init()
上面都是默认配置,直接使用默认配置
new WOW().init()
!!注意
这里单独安装了animate.css,它的类名我们可以从官网复制。它和wow里面自己依赖的样式名不一样,缺少了前缀animate__
使用
<div class="wow animate__animated animate__bounce"></div>
滚动动画没生效,浏览器下面有错误WOW.js cannot detect dom mutations, please call .sync() after loading new content.
MutationObserver is not supported by your browser.
百度得知需要支持异步的内容,改成这样。提示是没有了,但是滚动动画还是无效。
new WOW({live: false}).init()
接下来,尝试在isClient中执行,或者import后执行,均无效无报错。
我在单个页面中单独引入wowjs,并在onMounted中初始化。来了个新的报错:Cannot set properties of undefined (setting 'getPropertyValue')
原因:查看源码得知,只是个很老的库了,直接导出的wow单例,里面用到的外部this,在vue3中肯定是没有的,自然在挂在一些方法的时候就报错了。
解决:
wow压缩包放入public文件中,在index.html中引入吧。生效 <script type="text/javascript" src="/wow.min.js"></script>
<script type="text/javascript">
new WOW().init()
</script>
wow.js,安装它。看源码了解到它写了UMD导出,可以使用。npm i wow.js animate.css
使用。样式还是跟上面一样,使用animate.css中的样式
// main.ts
import 'animate.css/animate.min.css'
import WOW from 'wow.js'
new WOW().init()
wow.js这个库作者已经废弃,推荐使用aos。这个就更好了,再次向下滚动后到视野会再次触发动画下面单独说一下aos 版本,npm介绍上还是第一版本
aos 有两个版本,第一版aos 有自己的少量动画,配置较少,且不能结合animate.css
使用第二版 aos@next,详细介绍到github仓库去看
安装
npm i aos@next animate.css
使用要用到它的配置项。这里我们还是使用animate.css,效果更多。就不需要引入aos的样式了
// main.ts
import 'animate.css/animate.min.css'
import AOS from 'aos'
AOS.init({
// 这个默认是关闭的,它会把`data-aos`上要写的动画样式名,自动加到class上,这样才会有第三方动画效果
useClassNames: true,
// 这个就是关闭掉初始化的样式名,默认值,也就是默认样式名是'aos-init'。这里选用第三方样式,就不要被它内置的干扰了,去掉它
initClassName: null,
// 这里的默认值是'aos-animate',我们替换为animate.css的样式名
animatedClassName: 'animate__animated'
})
在公共样式表做样式覆盖
[data-aos] {
visibility: hidden;
}
[data-aos].animate__animated {
visibility: visible;
}
最后使用起来
<div data-aos="animate__fadeInLeft"></div>
最后配置好的项目,我放到这里gitee,直接取用
最新vite + ssg 项目配置地址
出于纯粹的兴趣,我很好奇如何按顺序创建PI,而不是在过程结果之后生成数字,而是让数字在过程本身生成时显示。如果是这种情况,那么数字可以自行产生,我可以对以前看到的数字实现垃圾收集,从而创建一个无限系列。结果只是在Pi系列之后每秒生成一个数字。这是我通过互联网筛选的结果:这是流行的计算机友好算法,类机器算法:defarccot(x,unity)xpow=unity/xn=1sign=1sum=0loopdoterm=xpow/nbreakifterm==0sum+=sign*(xpow/n)xpow/=x*xn+=2sign=-signendsumenddefcalc_pi(digits
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby
使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta
我对最新版本的Rails有疑问。我创建了一个新应用程序(railsnewMyProject),但我没有脚本/生成,只有脚本/rails,当我输入ruby./script/railsgeneratepluginmy_plugin"Couldnotfindgeneratorplugin.".你知道如何生成插件模板吗?没有这个命令可以创建插件吗?PS:我正在使用Rails3.2.1和ruby1.8.7[universal-darwin11.0] 最佳答案 随着Rails3.2.0的发布,插件生成器已经被移除。查看变更日志here.现在
如何使用RSpec::Core::RakeTask初始化RSpecRake任务?require'rspec/core/rake_task'RSpec::Core::RakeTask.newdo|t|#whatdoIputinhere?endInitialize函数记录在http://rubydoc.info/github/rspec/rspec-core/RSpec/Core/RakeTask#initialize-instance_method没有很好的记录;它只是说:-(RakeTask)initialize(*args,&task_block)AnewinstanceofRake
我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘
Sinatra新手;我正在运行一些rspec测试,但在日志中收到了一堆不需要的噪音。如何消除日志中过多的噪音?我仔细检查了环境是否设置为:test,这意味着记录器级别应设置为WARN而不是DEBUG。spec_helper:require"./app"require"sinatra"require"rspec"require"rack/test"require"database_cleaner"require"factory_girl"set:environment,:testFactoryGirl.definition_file_paths=%w{./factories./test/
关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion为什么SecureRandom.uuid创建一个唯一的字符串?SecureRandom.uuid#=>"35cb4e30-54e1-49f9-b5ce-4134799eb2c0"SecureRandom.uuid方法创建的字符串从不重复?
我已经像这样安装了一个新的Rails项目:$railsnewsite它执行并到达:bundleinstall但是当它似乎尝试安装依赖项时我得到了这个错误Gem::Ext::BuildError:ERROR:Failedtobuildgemnativeextension./System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/rubyextconf.rbcheckingforlibkern/OSAtomic.h...yescreatingMakefilemake"DESTDIR="cleanmake"DESTDIR="