企业官网
使用 VitePress 构建现代化的企业官网,展示公司形象、产品服务、团队实力和企业文化。
项目概述
企业官网是公司对外展示的重要窗口,需要专业的设计和良好的用户体验。VitePress 凭借其灵活的主题定制能力和优秀的性能表现,是构建企业官网的理想选择。
核心特性
- 🏢 企业形象 - 专业的品牌展示和企业介绍
- 📦 产品展示 - 丰富的产品介绍和案例展示
- 👥 团队介绍 - 展示核心团队和企业文化
- 📰 新闻动态 - 企业资讯和行业动态
- 📞 联系方式 - 多种联系方式和在线咨询
- 🌐 多语言 - 支持国际化多语言版本
- 📱 响应式 - 完美适配各种设备
- 🚀 高性能 - 快速加载和优秀的SEO
技术架构
核心技术栈
json
{
"framework": "VitePress",
"language": "TypeScript",
"styling": "CSS3 + Tailwind CSS",
"components": "Vue 3",
"tools": [
"Swiper.js",
"AOS Animation",
"EmailJS",
"Google Analytics"
]
}
项目结构
company-website/
├── docs/
│ ├── .vitepress/
│ │ ├── config.ts
│ │ ├── theme/
│ │ │ ├── index.ts
│ │ │ ├── Layout.vue
│ │ │ └── components/
│ │ │ ├── Hero.vue
│ │ │ ├── ProductCard.vue
│ │ │ ├── TeamMember.vue
│ │ │ └── ContactForm.vue
│ │ └── public/
│ ├── about/
│ ├── products/
│ ├── team/
│ ├── news/
│ ├── contact/
│ └── index.md
├── assets/
│ ├── images/
│ └── styles/
└── package.json
实现步骤
1. 项目初始化
bash
# 创建项目
npm create vitepress@latest company-website
cd company-website
# 安装依赖
npm install
npm install -D tailwindcss autoprefixer swiper aos emailjs-com
2. 配置 VitePress
typescript
// .vitepress/config.ts
import { defineConfig } from 'vitepress'
export default defineConfig({
title: '科技创新有限公司',
description: '专注于前沿技术研发和创新解决方案',
head: [
['link', { rel: 'icon', href: '/favicon.ico' }],
['meta', { name: 'viewport', content: 'width=device-width, initial-scale=1.0' }],
['meta', { property: 'og:type', content: 'website' }],
['meta', { property: 'og:title', content: '科技创新有限公司' }],
['meta', { property: 'og:description', content: '专注于前沿技术研发和创新解决方案' }],
['link', { rel: 'preconnect', href: 'https://fonts.googleapis.com' }],
['link', { rel: 'preconnect', href: 'https://fonts.gstatic.com', crossorigin: '' }],
['link', { href: 'https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap', rel: 'stylesheet' }]
],
themeConfig: {
logo: '/logo.svg',
nav: [
{ text: '首页', link: '/' },
{ text: '关于我们', link: '/about/' },
{
text: '产品服务',
items: [
{ text: '产品概览', link: '/products/' },
{ text: '解决方案', link: '/products/solutions' },
{ text: '技术服务', link: '/products/services' }
]
},
{ text: '团队', link: '/team/' },
{ text: '新闻动态', link: '/news/' },
{ text: '联系我们', link: '/contact/' }
],
footer: {
message: '© 2024 科技创新有限公司 版权所有',
copyright: 'ICP备案号:京ICP备12345678号-1'
},
socialLinks: [
{ icon: 'github', link: 'https://github.com/company' },
{ icon: 'twitter', link: 'https://twitter.com/company' },
{ icon: 'linkedin', link: 'https://linkedin.com/company/company' }
]
},
// 自定义 CSS
vite: {
css: {
postcss: {
plugins: [
require('tailwindcss'),
require('autoprefixer')
]
}
}
}
})
3. 首页布局
vue
<!-- .vitepress/theme/Layout.vue -->
<template>
<Layout>
<template #home-hero-before>
<HeroSection v-if="isHomePage" />
</template>
<template #home-features-after>
<div v-if="isHomePage" class="home-content">
<AboutSection />
<ProductsSection />
<TeamSection />
<NewsSection />
<ContactSection />
</div>
</template>
</Layout>
</template>
<script setup>
import { computed } from 'vue'
import { useData } from 'vitepress'
import DefaultTheme from 'vitepress/theme'
import HeroSection from './components/HeroSection.vue'
import AboutSection from './components/AboutSection.vue'
import ProductsSection from './components/ProductsSection.vue'
import TeamSection from './components/TeamSection.vue'
import NewsSection from './components/NewsSection.vue'
import ContactSection from './components/ContactSection.vue'
const { Layout } = DefaultTheme
const { page } = useData()
const isHomePage = computed(() => {
return page.value.relativePath === 'index.md'
})
</script>
<style>
.home-content {
max-width: 1200px;
margin: 0 auto;
padding: 0 20px;
}
.home-content section {
margin: 80px 0;
}
@media (max-width: 768px) {
.home-content {
padding: 0 15px;
}
.home-content section {
margin: 60px 0;
}
}
</style>
4. 英雄区域组件
vue
<!-- .vitepress/theme/components/HeroSection.vue -->
<template>
<section class="hero-section">
<div class="hero-background">
<div class="hero-overlay"></div>
<video
autoplay
muted
loop
class="hero-video"
>
<source src="/videos/hero-bg.mp4" type="video/mp4">
</video>
</div>
<div class="hero-content">
<div class="container">
<h1 class="hero-title" data-aos="fade-up">
引领科技创新
<span class="highlight">改变未来</span>
</h1>
<p class="hero-description" data-aos="fade-up" data-aos-delay="200">
我们专注于前沿技术研发,为企业提供创新的解决方案,
助力数字化转型,共创美好未来。
</p>
<div class="hero-actions" data-aos="fade-up" data-aos-delay="400">
<a href="/products/" class="btn btn-primary">
了解产品
</a>
<a href="/contact/" class="btn btn-secondary">
联系我们
</a>
</div>
</div>
</div>
<div class="hero-scroll">
<div class="scroll-indicator">
<span></span>
</div>
</div>
</section>
</template>
<script setup>
import { onMounted } from 'vue'
import AOS from 'aos'
onMounted(() => {
AOS.init({
duration: 1000,
once: true
})
})
</script>
<style scoped>
.hero-section {
position: relative;
height: 100vh;
min-height: 600px;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
}
.hero-background {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
}
.hero-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.3) 100%);
z-index: 1;
}
.hero-video {
width: 100%;
height: 100%;
object-fit: cover;
}
.hero-content {
position: relative;
z-index: 2;
text-align: center;
color: white;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 0 20px;
}
.hero-title {
font-size: 3.5rem;
font-weight: 700;
line-height: 1.2;
margin-bottom: 1.5rem;
}
.highlight {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.hero-description {
font-size: 1.25rem;
line-height: 1.6;
margin-bottom: 2.5rem;
max-width: 600px;
margin-left: auto;
margin-right: auto;
opacity: 0.9;
}
.hero-actions {
display: flex;
gap: 1rem;
justify-content: center;
flex-wrap: wrap;
}
.btn {
display: inline-block;
padding: 12px 30px;
border-radius: 50px;
font-weight: 600;
text-decoration: none;
transition: all 0.3s ease;
border: 2px solid transparent;
}
.btn-primary {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 10px 25px rgba(102, 126, 234, 0.3);
}
.btn-secondary {
background: transparent;
color: white;
border-color: white;
}
.btn-secondary:hover {
background: white;
color: #333;
transform: translateY(-2px);
}
.hero-scroll {
position: absolute;
bottom: 30px;
left: 50%;
transform: translateX(-50%);
z-index: 2;
}
.scroll-indicator {
width: 30px;
height: 50px;
border: 2px solid rgba(255, 255, 255, 0.5);
border-radius: 25px;
position: relative;
cursor: pointer;
}
.scroll-indicator span {
position: absolute;
top: 8px;
left: 50%;
width: 4px;
height: 8px;
background: rgba(255, 255, 255, 0.8);
border-radius: 2px;
transform: translateX(-50%);
animation: scroll 2s infinite;
}
@keyframes scroll {
0% { opacity: 0; transform: translateX(-50%) translateY(0); }
50% { opacity: 1; }
100% { opacity: 0; transform: translateX(-50%) translateY(15px); }
}
@media (max-width: 768px) {
.hero-title {
font-size: 2.5rem;
}
.hero-description {
font-size: 1.1rem;
}
.hero-actions {
flex-direction: column;
align-items: center;
}
.btn {
width: 200px;
}
}
</style>
5. 产品展示组件
vue
<!-- .vitepress/theme/components/ProductsSection.vue -->
<template>
<section class="products-section">
<div class="container">
<div class="section-header" data-aos="fade-up">
<h2>我们的产品</h2>
<p>为不同行业提供专业的技术解决方案</p>
</div>
<div class="products-grid">
<ProductCard
v-for="product in products"
:key="product.id"
:product="product"
data-aos="fade-up"
:data-aos-delay="product.id * 100"
/>
</div>
<div class="section-footer" data-aos="fade-up">
<a href="/products/" class="btn btn-outline">
查看所有产品
</a>
</div>
</div>
</section>
</template>
<script setup>
import { ref } from 'vue'
import ProductCard from './ProductCard.vue'
const products = ref([
{
id: 1,
title: '智能数据分析平台',
description: '基于AI的大数据分析平台,帮助企业挖掘数据价值,做出智能决策。',
image: '/images/products/data-platform.jpg',
features: ['实时数据处理', '智能可视化', '预测分析'],
link: '/products/data-platform'
},
{
id: 2,
title: '云原生开发框架',
description: '现代化的微服务开发框架,支持容器化部署和自动扩缩容。',
image: '/images/products/cloud-framework.jpg',
features: ['微服务架构', '容器化部署', '自动扩缩容'],
link: '/products/cloud-framework'
},
{
id: 3,
title: '企业协作平台',
description: '一站式企业协作解决方案,提升团队协作效率和沟通质量。',
image: '/images/products/collaboration.jpg',
features: ['即时通讯', '项目管理', '文档协作'],
link: '/products/collaboration'
}
])
</script>
<style scoped>
.products-section {
padding: 80px 0;
background: #f8fafc;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 0 20px;
}
.section-header {
text-align: center;
margin-bottom: 60px;
}
.section-header h2 {
font-size: 2.5rem;
font-weight: 700;
color: #1a202c;
margin-bottom: 1rem;
}
.section-header p {
font-size: 1.1rem;
color: #718096;
max-width: 600px;
margin: 0 auto;
}
.products-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
gap: 30px;
margin-bottom: 60px;
}
.section-footer {
text-align: center;
}
.btn {
display: inline-block;
padding: 12px 30px;
border-radius: 8px;
font-weight: 600;
text-decoration: none;
transition: all 0.3s ease;
}
.btn-outline {
background: transparent;
color: #667eea;
border: 2px solid #667eea;
}
.btn-outline:hover {
background: #667eea;
color: white;
transform: translateY(-2px);
box-shadow: 0 10px 25px rgba(102, 126, 234, 0.2);
}
@media (max-width: 768px) {
.products-grid {
grid-template-columns: 1fr;
gap: 20px;
}
.section-header h2 {
font-size: 2rem;
}
}
</style>
6. 产品卡片组件
vue
<!-- .vitepress/theme/components/ProductCard.vue -->
<template>
<div class="product-card">
<div class="card-image">
<img :src="product.image" :alt="product.title" />
<div class="card-overlay">
<a :href="product.link" class="card-link">
了解详情
</a>
</div>
</div>
<div class="card-content">
<h3 class="card-title">{{ product.title }}</h3>
<p class="card-description">{{ product.description }}</p>
<div class="card-features">
<span
v-for="feature in product.features"
:key="feature"
class="feature-tag"
>
{{ feature }}
</span>
</div>
</div>
</div>
</template>
<script setup>
defineProps({
product: {
type: Object,
required: true
}
})
</script>
<style scoped>
.product-card {
background: white;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
transition: all 0.3s ease;
}
.product-card:hover {
transform: translateY(-5px);
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
}
.card-image {
position: relative;
height: 200px;
overflow: hidden;
}
.card-image img {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.3s ease;
}
.product-card:hover .card-image img {
transform: scale(1.05);
}
.card-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.7);
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
transition: opacity 0.3s ease;
}
.product-card:hover .card-overlay {
opacity: 1;
}
.card-link {
color: white;
text-decoration: none;
padding: 10px 20px;
border: 2px solid white;
border-radius: 25px;
font-weight: 600;
transition: all 0.3s ease;
}
.card-link:hover {
background: white;
color: #333;
}
.card-content {
padding: 25px;
}
.card-title {
font-size: 1.25rem;
font-weight: 600;
color: #1a202c;
margin-bottom: 10px;
}
.card-description {
color: #718096;
line-height: 1.6;
margin-bottom: 20px;
}
.card-features {
display: flex;
flex-wrap: wrap;
gap: 8px;
}
.feature-tag {
background: #e2e8f0;
color: #4a5568;
padding: 4px 12px;
border-radius: 20px;
font-size: 0.875rem;
font-weight: 500;
}
</style>
7. 团队展示组件
vue
<!-- .vitepress/theme/components/TeamSection.vue -->
<template>
<section class="team-section">
<div class="container">
<div class="section-header" data-aos="fade-up">
<h2>核心团队</h2>
<p>汇聚行业精英,共创技术未来</p>
</div>
<div class="team-grid">
<TeamMember
v-for="member in teamMembers"
:key="member.id"
:member="member"
data-aos="fade-up"
:data-aos-delay="member.id * 100"
/>
</div>
</div>
</section>
</template>
<script setup>
import { ref } from 'vue'
import TeamMember from './TeamMember.vue'
const teamMembers = ref([
{
id: 1,
name: '张伟',
position: '首席技术官',
avatar: '/images/team/zhang-wei.jpg',
bio: '15年技术研发经验,专注于云计算和人工智能领域',
social: {
linkedin: 'https://linkedin.com/in/zhangwei',
github: 'https://github.com/zhangwei'
}
},
{
id: 2,
name: '李娜',
position: '产品总监',
avatar: '/images/team/li-na.jpg',
bio: '10年产品管理经验,擅长用户体验设计和产品策略',
social: {
linkedin: 'https://linkedin.com/in/lina',
twitter: 'https://twitter.com/lina'
}
},
{
id: 3,
name: '王强',
position: '架构师',
avatar: '/images/team/wang-qiang.jpg',
bio: '资深系统架构师,在大规模分布式系统设计方面有丰富经验',
social: {
linkedin: 'https://linkedin.com/in/wangqiang',
github: 'https://github.com/wangqiang'
}
},
{
id: 4,
name: '刘敏',
position: '设计总监',
avatar: '/images/team/liu-min.jpg',
bio: '创意设计专家,致力于打造优秀的用户界面和体验',
social: {
linkedin: 'https://linkedin.com/in/liumin',
dribbble: 'https://dribbble.com/liumin'
}
}
])
</script>
<style scoped>
.team-section {
padding: 80px 0;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 0 20px;
}
.section-header {
text-align: center;
margin-bottom: 60px;
}
.section-header h2 {
font-size: 2.5rem;
font-weight: 700;
color: #1a202c;
margin-bottom: 1rem;
}
.section-header p {
font-size: 1.1rem;
color: #718096;
}
.team-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 30px;
}
@media (max-width: 768px) {
.team-grid {
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
}
.section-header h2 {
font-size: 2rem;
}
}
</style>
8. 联系表单组件
vue
<!-- .vitepress/theme/components/ContactForm.vue -->
<template>
<div class="contact-form">
<form @submit.prevent="submitForm" class="form">
<div class="form-group">
<label for="name">姓名 *</label>
<input
id="name"
v-model="form.name"
type="text"
required
placeholder="请输入您的姓名"
/>
</div>
<div class="form-group">
<label for="email">邮箱 *</label>
<input
id="email"
v-model="form.email"
type="email"
required
placeholder="请输入您的邮箱"
/>
</div>
<div class="form-group">
<label for="company">公司</label>
<input
id="company"
v-model="form.company"
type="text"
placeholder="请输入您的公司名称"
/>
</div>
<div class="form-group">
<label for="subject">主题 *</label>
<select id="subject" v-model="form.subject" required>
<option value="">请选择咨询主题</option>
<option value="product">产品咨询</option>
<option value="cooperation">合作洽谈</option>
<option value="support">技术支持</option>
<option value="other">其他</option>
</select>
</div>
<div class="form-group">
<label for="message">留言 *</label>
<textarea
id="message"
v-model="form.message"
required
rows="5"
placeholder="请详细描述您的需求或问题"
></textarea>
</div>
<button
type="submit"
class="submit-btn"
:disabled="isSubmitting"
>
{{ isSubmitting ? '发送中...' : '发送消息' }}
</button>
</form>
<div v-if="submitStatus" class="status-message" :class="submitStatus.type">
{{ submitStatus.message }}
</div>
</div>
</template>
<script setup>
import { ref, reactive } from 'vue'
import emailjs from 'emailjs-com'
const form = reactive({
name: '',
email: '',
company: '',
subject: '',
message: ''
})
const isSubmitting = ref(false)
const submitStatus = ref(null)
async function submitForm() {
isSubmitting.value = true
submitStatus.value = null
try {
await emailjs.send(
'your_service_id',
'your_template_id',
{
from_name: form.name,
from_email: form.email,
company: form.company,
subject: form.subject,
message: form.message
},
'your_public_key'
)
submitStatus.value = {
type: 'success',
message: '消息发送成功!我们会尽快与您联系。'
}
// 重置表单
Object.keys(form).forEach(key => {
form[key] = ''
})
} catch (error) {
submitStatus.value = {
type: 'error',
message: '发送失败,请稍后重试或直接联系我们。'
}
} finally {
isSubmitting.value = false
}
}
</script>
<style scoped>
.contact-form {
max-width: 600px;
margin: 0 auto;
}
.form {
background: white;
padding: 40px;
border-radius: 12px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
}
.form-group {
margin-bottom: 25px;
}
.form-group label {
display: block;
margin-bottom: 8px;
font-weight: 600;
color: #374151;
}
.form-group input,
.form-group select,
.form-group textarea {
width: 100%;
padding: 12px 16px;
border: 2px solid #e5e7eb;
border-radius: 8px;
font-size: 16px;
transition: border-color 0.3s ease;
}
.form-group input:focus,
.form-group select:focus,
.form-group textarea:focus {
outline: none;
border-color: #667eea;
}
.submit-btn {
width: 100%;
padding: 15px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
border-radius: 8px;
font-size: 16px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
}
.submit-btn:hover:not(:disabled) {
transform: translateY(-2px);
box-shadow: 0 10px 25px rgba(102, 126, 234, 0.3);
}
.submit-btn:disabled {
opacity: 0.7;
cursor: not-allowed;
}
.status-message {
margin-top: 20px;
padding: 15px;
border-radius: 8px;
text-align: center;
font-weight: 500;
}
.status-message.success {
background: #d1fae5;
color: #065f46;
border: 1px solid #a7f3d0;
}
.status-message.error {
background: #fee2e2;
color: #991b1b;
border: 1px solid #fca5a5;
}
</style>
高级功能
1. 多语言支持
typescript
// .vitepress/config.ts
export default defineConfig({
locales: {
root: {
label: '简体中文',
lang: 'zh-CN',
title: '科技创新有限公司',
description: '专注于前沿技术研发和创新解决方案'
},
en: {
label: 'English',
lang: 'en-US',
title: 'Tech Innovation Co., Ltd.',
description: 'Focus on cutting-edge technology R&D and innovative solutions',
themeConfig: {
nav: [
{ text: 'Home', link: '/en/' },
{ text: 'About', link: '/en/about/' },
{ text: 'Products', link: '/en/products/' },
{ text: 'Team', link: '/en/team/' },
{ text: 'News', link: '/en/news/' },
{ text: 'Contact', link: '/en/contact/' }
]
}
}
}
})
2. SEO 优化
vue
<!-- .vitepress/theme/components/SEOHead.vue -->
<template>
<Head>
<title>{{ pageTitle }}</title>
<meta name="description" :content="pageDescription" />
<meta property="og:title" :content="pageTitle" />
<meta property="og:description" :content="pageDescription" />
<meta property="og:image" :content="pageImage" />
<meta property="og:url" :content="pageUrl" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" :content="pageTitle" />
<meta name="twitter:description" :content="pageDescription" />
<meta name="twitter:image" :content="pageImage" />
<link rel="canonical" :href="pageUrl" />
<script type="application/ld+json" v-html="structuredData"></script>
</Head>
</template>
<script setup>
import { computed } from 'vue'
import { useData } from 'vitepress'
const { page, site } = useData()
const pageTitle = computed(() => {
return page.value.title ? `${page.value.title} - ${site.value.title}` : site.value.title
})
const pageDescription = computed(() => {
return page.value.description || site.value.description
})
const pageImage = computed(() => {
return page.value.frontmatter.image || '/images/og-image.jpg'
})
const pageUrl = computed(() => {
return `${site.value.base}${page.value.relativePath.replace('.md', '.html')}`
})
const structuredData = computed(() => {
return JSON.stringify({
"@context": "https://schema.org",
"@type": "Organization",
"name": "科技创新有限公司",
"url": site.value.base,
"logo": `${site.value.base}/logo.png`,
"description": site.value.description,
"address": {
"@type": "PostalAddress",
"streetAddress": "科技园区创新大厦",
"addressLocality": "北京",
"addressCountry": "CN"
},
"contactPoint": {
"@type": "ContactPoint",
"telephone": "+86-10-12345678",
"contactType": "customer service"
}
})
})
</script>
3. 性能监控
javascript
// .vitepress/theme/utils/analytics.js
export function initAnalytics() {
// Google Analytics
if (typeof gtag !== 'undefined') {
gtag('config', 'GA_MEASUREMENT_ID', {
page_title: document.title,
page_location: window.location.href
})
}
// 性能监控
if ('performance' in window) {
window.addEventListener('load', () => {
const perfData = performance.getEntriesByType('navigation')[0]
// 发送性能数据
gtag('event', 'page_load_time', {
event_category: 'Performance',
event_label: 'Load Time',
value: Math.round(perfData.loadEventEnd - perfData.fetchStart)
})
})
}
}
部署配置
Docker 部署
dockerfile
# Dockerfile
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM nginx:alpine
COPY --from=builder /app/docs/.vitepress/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
nginx
# nginx.conf
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
index index.html;
location / {
try_files $uri $uri/ $uri.html /index.html;
}
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
}
}
CI/CD 流水线
yaml
# .github/workflows/deploy.yml
name: Deploy Company Website
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm run test
- name: Build
run: npm run build
env:
NODE_ENV: production
- name: Deploy to staging
if: github.event_name == 'pull_request'
run: |
echo "Deploy to staging environment"
# 部署到测试环境的命令
- name: Deploy to production
if: github.ref == 'refs/heads/main'
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: docs/.vitepress/dist
custom_domain: company.example.com
- name: Notify deployment
if: always()
uses: 8398a7/action-slack@v3
with:
status: ${{ job.status }}
webhook_url: ${{ secrets.SLACK_WEBHOOK }}
最佳实践
1. 内容管理
- 内容策略 - 制定清晰的内容更新计划
- 版本控制 - 使用 Git 管理内容变更
- 审核流程 - 建立内容审核和发布流程
2. 用户体验
- 加载速度 - 优化图片和资源加载
- 移动适配 - 确保移动设备良好体验
- 无障碍访问 - 遵循 WCAG 无障碍标准
3. 安全性
- HTTPS - 启用 SSL 证书
- 内容安全 - 设置 CSP 头部
- 定期更新 - 保持依赖包最新版本
示例项目
完整的示例项目可以在 GitHub 上查看。
在线演示
- 企业官网: company.example.com
- 源代码: GitHub Repository
功能特色
- ✅ 响应式设计
- ✅ 多语言支持
- ✅ SEO 优化
- ✅ 性能监控
- ✅ 自动化部署
- ✅ 内容管理系统
通过这个案例,你可以学习如何使用 VitePress 构建专业的企业官网,包括品牌展示、产品介绍、团队展示和客户联系等核心功能。