Skip to content

UniApp Template

The UniApp template provides a cross-platform development solution for H5, Mini Programs, and App, perfect for building applications that run on multiple platforms with a single codebase.

Technical Stack

  • UniApp - Cross-platform framework
  • Vue 3 - Progressive JavaScript framework
  • TypeScript - Type-safe development
  • Vite - Fast build tool and dev server
  • Tailwind CSS - Utility-first CSS framework
  • Vue i18n - Internationalization

Quick Start

1. Create Project

bash
# Initialize project
vup init my-uniapp-project
cd my-uniapp-project

# Add UniApp template
vup add my-uniapp

2. Install Dependencies

bash
# Install dependencies
pnpm install

3. Start Development

bash
# Start development server
cd apps/my-uniapp
pnpm dev

The application will be available at http://localhost:9301.

Supported Platforms

  • H5 - Web applications
  • WeChat Mini Program - WeChat mini program
  • Alipay Mini Program - Alipay mini program
  • Baidu Mini Program - Baidu mini program
  • ByteDance Mini Program - ByteDance mini program
  • QQ Mini Program - QQ mini program
  • App - iOS and Android applications

Project Structure

apps/my-uniapp/
├── src/
│   ├── assets/           # Static assets
│   │   └── images/       # Image files
│   ├── locales/          # Internationalization
│   │   ├── index.ts      # i18n configuration
│   │   ├── en-US.ts      # English translations
│   │   └── zh-CN.ts      # Chinese translations
│   ├── pages/            # Pages
│   │   └── index/        # Home page
│   │       ├── index.vue # Home page component
│   │       └── index.scss # Home page styles
│   ├── static/           # Static resources
│   │   └── logo.png      # Logo image
│   ├── App.vue           # Root component
│   ├── main.ts           # Application entry point
│   ├── manifest.json     # App configuration
│   ├── pages.json        # Pages configuration
│   └── uni.scss          # Global styles
├── package.json          # Dependencies and scripts
├── tsconfig.json         # TypeScript configuration
├── tailwind.config.js    # Tailwind CSS configuration
└── vite.config.ts        # Vite configuration

Core Features

Cross-platform Development

vue
<!-- pages/index/index.vue -->
<template>
  <view class="container">
    <image class="logo" src="/static/logo.png" mode="aspectFit"></image>
    <text class="title">{{ title }}</text>
    <text class="description">{{ description }}</text>
    <button class="btn" @click="handleClick">Click Me</button>
  </view>
</template>

<script setup lang="ts">
import { ref } from 'vue';

const title = ref('UniApp Application');
const description = ref('Cross-platform development with UniApp');

const handleClick = () => {
  uni.showToast({
    title: 'Button clicked!',
    icon: 'success',
  });
};
</script>

<style lang="scss" scoped>
.container {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  padding: 20px;
}

.logo {
  width: 200px;
  height: 200px;
  margin-bottom: 20px;
}

.title {
  font-size: 24px;
  font-weight: bold;
  margin-bottom: 10px;
  color: #333;
}

.description {
  font-size: 16px;
  color: #666;
  margin-bottom: 30px;
  text-align: center;
}

.btn {
  background-color: #007aff;
  color: white;
  border: none;
  border-radius: 8px;
  padding: 12px 24px;
  font-size: 16px;
}
</style>

Platform-specific Code

vue
<template>
  <view class="platform-specific">
    <!-- #ifdef H5 -->
    <view class="h5-only">This content only shows on H5</view>
    <!-- #endif -->

    <!-- #ifdef MP-WEIXIN -->
    <view class="wechat-only"
      >This content only shows on WeChat Mini Program</view
    >
    <!-- #endif -->

    <!-- #ifdef APP-PLUS -->
    <view class="app-only">This content only shows on App</view>
    <!-- #endif -->
  </view>
</template>

<script setup lang="ts">
// Platform-specific logic
// #ifdef H5
const isH5 = true;
// #endif

// #ifdef MP-WEIXIN
const isWeChat = true;
// #endif

// #ifdef APP-PLUS
const isApp = true;
// #endif
</script>

Internationalization

typescript
// locales/en-US.ts
export default {
  common: {
    title: 'UniApp Application',
    description: 'Cross-platform development with UniApp',
    button: 'Click Me',
  },
  navigation: {
    home: 'Home',
    about: 'About',
  },
};
typescript
// locales/zh-CN.ts
export default {
  common: {
    title: 'UniApp 应用',
    description: '使用 UniApp 进行跨平台开发',
    button: '点击我',
  },
  navigation: {
    home: '首页',
    about: '关于',
  },
};

Tailwind CSS Styling

vue
<template>
  <view class="min-h-screen bg-gray-100">
    <view class="container mx-auto px-4 py-8">
      <view class="bg-white rounded-lg shadow-md p-6">
        <text class="text-2xl font-bold text-gray-900 mb-4">
          {{ $t('common.title') }}
        </text>
        <text class="text-gray-600 mb-6">
          {{ $t('common.description') }}
        </text>
        <button
          class="bg-blue-500 hover:bg-blue-600 text-white font-bold py-2 px-4 rounded"
          @click="handleClick"
        >
          {{ $t('common.button') }}
        </button>
      </view>
    </view>
  </view>
</template>

Development Tools

Vite Configuration

typescript
// vite.config.ts
import { defineConfig } from 'vite';
import uni from '@dcloudio/vite-plugin-uni';
import { resolve } from 'path';

export default defineConfig({
  plugins: [uni()],
  resolve: {
    alias: {
      '@': resolve(__dirname, './src'),
      '@shared': resolve(__dirname, '../../_shared'),
    },
  },
  css: {
    postcss: resolve(__dirname, '../../postcss.config.js'),
  },
  server: {
    host: '0.0.0.0',
    port: 9301,
    open: false,
  },
});

TypeScript Configuration

json
// tsconfig.json
{
  "extends": "../../tsconfig.json",
  "compilerOptions": {
    "outDir": "./dist",
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"],
      "@shared/*": ["../../_shared/*"]
    }
  },
  "include": ["src/**/*", "src/**/*.vue", "src/*.vue"]
}

Tailwind CSS Configuration

javascript
// tailwind.config.js
module.exports = {
  content: ['./src/**/*.{vue,js,ts,jsx,tsx}', './src/**/*.html'],
  theme: {
    extend: {},
  },
  plugins: [],
  corePlugins: {
    preflight: false, // Disable preflight for UniApp
  },
};

Available Scripts

json
{
  "scripts": {
    "dev": "uni dev",
    "build": "uni build",
    "build:h5": "uni build --platform h5",
    "build:mp-weixin": "uni build --platform mp-weixin",
    "build:app": "uni build --platform app",
    "lint": "eslint src/ --ext .vue,.ts,.js",
    "lint:fix": "eslint src/ --ext .vue,.ts,.js --fix",
    "format": "prettier --write \"src/**/*.{js,ts,vue,json,css,scss}\"",
    "format:check": "prettier --check \"src/**/*.{js,ts,vue,json,css,scss}\""
  }
}

Platform-specific Configuration

H5 Configuration

json
// manifest.json
{
  "h5": {
    "title": "UniApp Application",
    "template": "index.html",
    "router": {
      "mode": "hash",
      "base": "./"
    },
    "optimization": {
      "treeShaking": {
        "enable": true
      }
    }
  }
}

Mini Program Configuration

json
// manifest.json
{
  "mp-weixin": {
    "appid": "your-appid",
    "setting": {
      "urlCheck": false,
      "es6": true,
      "enhance": true,
      "postcss": true,
      "minified": true
    },
    "usingComponents": true
  }
}

App Configuration

json
// manifest.json
{
  "app-plus": {
    "usingComponents": true,
    "nvueStyleCompiler": "uni-app",
    "compilerVersion": 3,
    "splashscreen": {
      "alwaysShowBeforeRender": true,
      "waiting": true,
      "autoclose": true,
      "delay": 0
    },
    "modules": {},
    "distribute": {
      "android": {
        "permissions": [
          "<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\" />",
          "<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\" />",
          "<uses-permission android:name=\"android.permission.VIBRATE\" />",
          "<uses-permission android:name=\"android.permission.READ_LOGS\" />",
          "<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\" />",
          "<uses-feature android:name=\"android.hardware.camera.autofocus\" />",
          "<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\" />",
          "<uses-permission android:name=\"android.permission.CAMERA\" />",
          "<uses-permission android:name=\"android.permission.GET_ACCOUNTS\" />",
          "<uses-permission android:name=\"android.permission.READ_PHONE_STATE\" />",
          "<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\" />",
          "<uses-permission android:name=\"android.permission.WAKE_LOCK\" />",
          "<uses-permission android:name=\"android.permission.FLASHLIGHT\" />",
          "<uses-feature android:name=\"android.hardware.camera\" />",
          "<uses-permission android:name=\"android.permission.WRITE_SETTINGS\" />"
        ]
      },
      "ios": {},
      "sdkConfigs": {}
    }
  }
}

Best Practices

Component Development

vue
<template>
  <view class="custom-component">
    <slot name="header"></slot>
    <view class="content">
      <slot></slot>
    </view>
    <slot name="footer"></slot>
  </view>
</template>

<script setup lang="ts">
interface Props {
  title?: string;
  visible?: boolean;
}

const props = withDefaults(defineProps<Props>(), {
  title: '',
  visible: true,
});

const emit = defineEmits<{
  click: [event: Event];
  change: [value: string];
}>();

const handleClick = (event: Event) => {
  emit('click', event);
};
</script>

<style lang="scss" scoped>
.custom-component {
  @apply p-4 bg-white rounded-lg shadow-md;
}
</style>

API Calls

typescript
// utils/api.ts
export interface ApiResponse<T = any> {
  code: number;
  message: string;
  data: T;
}

export class ApiService {
  private baseURL: string;

  constructor(baseURL: string) {
    this.baseURL = baseURL;
  }

  async request<T = any>(
    url: string,
    options: RequestOptions = {}
  ): Promise<ApiResponse<T>> {
    try {
      const response = await uni.request({
        url: `${this.baseURL}${url}`,
        method: options.method || 'GET',
        data: options.data,
        header: {
          'Content-Type': 'application/json',
          ...options.header,
        },
      });

      return response.data as ApiResponse<T>;
    } catch (error) {
      throw new Error(`API request failed: ${error.message}`);
    }
  }
}

interface RequestOptions {
  method?: 'GET' | 'POST' | 'PUT' | 'DELETE';
  data?: any;
  header?: Record<string, string>;
}

Build and Deployment

H5 Build

bash
# Build for H5
pnpm build:h5

# The built files will be in the dist/build/h5 directory

Mini Program Build

bash
# Build for WeChat Mini Program
pnpm build:mp-weixin

# The built files will be in the dist/build/mp-weixin directory

App Build

bash
# Build for App
pnpm build:app

# The built files will be in the dist/build/app directory