尝鲜 Vite + Svelte + Tailwindcss 开发项目

4,107 阅读2分钟

背景

最近需要给App写几个h5页面,没有复杂的交互,纯展示的内容多。如果引入Vue的话,有点杀鸡焉用牛刀的感觉!之前了解过学习过Svelte,正好是一次尝鲜的机会! 点击学习Svelte 入门教程!

image.png

初始化项目

Vite官方提供了一个SvelteSvelte-ts两个版本的模板——在线体验地址

# npm 6.x
npm create vite@latest vite-svelte --template svelte

# npm 7+, extra double-dash is needed:
npm create vite@latest vite-svelte -- --template svelte

# yarn
yarn create vite vite-svelte --template svelte

# pnpm
pnpm create vite vite-svelte -- --template svelte

安装运行项目:

cd vite-svelte

yarn 

yarn dev

open http://localhost:30000

image.png

引入路由

我用的是svelte-spa-router,因为它的使用方式更接近vue-router,用起来简单。

yarn add svelte-spa-router
// router/index.js
import List from '@/views/List.svelte'
import Detail from '@/views/Detail.svelte'

export default {
  '/list': List,
  '/detail/:id': Detail
}

// App.svelte
import Router, {link} from 'svelte-spa-router';
import routes from './router/index.js'

<Router {routes} />

use:link

import Router, {link} from 'svelte-spa-router';

<a href="javascript;" use:link={'/list'}>To List</a>
<a href="javascript;" use:link={'/detail/1?name=finget'}>To Detail</a>

编程式路由

svelte-spa-router提供了三个方法push,pop,replace,看名字也知道是什么意思了。

import {push, pop, replace} from 'svelte-spa-router'

push('/detail/42')

pop()

replace('/list')

获取路由参数

// views/Detail.svelte
<script>
  import {querystring} from 'svelte-spa-router';
  export let params = {}
</script>

<div>
  <p>params id is {params.id}</p> 
  <p>query is {$querystring}</p>
</div>

动态组件

svelte-spa-router也是支持异步动态组件的。

// router/index.js
import {wrap} from 'svelte-spa-router/wrap'
import List from '@/views/List.svelte'

export default {
  '/list': List,
  '/detail/:id': wrap({
    asyncComponent: () => import('@/views/Detail.svelte')
  })
}

引入tailwindcss

安装官网的方式安装:

yarn add -D tailwindcss postcss autoprefixer
npx tailwindcss init -p

这时候重启项目,正常情况下会报错require() of ES modules is not supported,不支持ES modules

image.png

解决方案在这里: github.com/vitejs/vite…

npx svelte-add@latest tailwindcss

接着再运行会提示没有安装svelte-preprocess,重新安装一下就行了。

image.png

yarn add svelte-preprocess -D

到这里tailwindcss就算成功引入了!

<a href="javascript;" class="font-medium text-xl underline text-red-400" use:link={'/list'}>To List</a>
<a href="javascript;" class="font-medium text-xl underline text-red-400" use:link={'/detail/1?name=finget'}>To Detail</a>

引入 axios

yarn add axios
// utils/request.js
// Api.js
import axios from "axios";

// Create a instance of axios to use the same base url.
const axiosAPI = axios.create({
  baseURL: "https://xxxx.typicode.com", // it's not recommended to have this info here.
  withCredentials: true,
  timeout: 10000
});

// implement a method to execute all the request from here.
const apiRequest = (method, url, request) => {
  const headers = {
    authorization: ""
  };
  //using the axios instance to perform the request that received from each http method
  return axiosAPI({
    method,
    url,
    data: request,
    headers
  }).then(res => {
    return Promise.resolve(res.data);
  }).catch(err => {
    return Promise.reject(err);
  });
};

// function to execute the http get request
const get = (url, request) => apiRequest("get", url, request);

// function to execute the http delete request
const deleteRequest = (url, request) => apiRequest("delete", url, request);

// function to execute the http post request
const post = (url, request) => apiRequest("post", url, request);

// function to execute the http put request
const put = (url, request) => apiRequest("put", url, request);

// function to execute the http path request
const patch = (url, request) => apiRequest("patch", url, request);

// expose your method to other services or actions
export { get, deleteRequest, post, put, patch };

proxy

// vite.config.js
...
export default defineConfig({
  return {
    ...
    server: {
      port: 3344,
      proxy: {
        '/api': {
          target: 'http://api.coindesk.com',
          changeOrigin: true,
          secure: true,
          pathRewrite: {
            '^/api': ''
          }
        }
      }
    },
    ...
  }
})

状态管理-实现一个简易的Toast组件

Svelte自带状态管理store,语法层面本文介绍太多,大家看下面的事例,运行一下项目,就能理解了,官网的教程写的特别好,更多的细节建议去Svelte 官网学习了解!

// components/Toast

// toasts.svelte
<script>
import { flip } from 'svelte/animate';
import { toasts } from './toastStore';
</script>

{#if $toasts.length}
  <div class="fixed top-0 z-50">
      <ul class="">
        {#each $toasts as toast (toast.id)}
          <li animate:flip class="totast text-white px-5 py-2 rounded-2xl mb-2">
            {@html toast.msg}
          </li>
        {/each}
      </ul>
  </div>
{/if}

// toastStore.js

import { writable } from 'svelte/store';

export const toasts = writable([]);

/**
 *
 * @param msg 提示信息,可以是任意html内容
 * @param type 信息类型
 * @param removeAfter 清除时间,单位:秒
 * @param handler 手动删除
 * @returns id of Toast
 */
export function addToast(msg, type = 'info', handler = false, removeAfter = 2000) {
  const id = new Date().valueOf() + msg;
  toasts.update((all) => [
    {
     id,
     msg,
     type,
     removeAfter
    },
    ...all
  ]);
  if(!handler) {
    setTimeout(() => {
      removeToast(id);
    }, removeAfter);
  }
  return id;
}

export function removeToast(id) {
  toasts.update((all) => all.filter((toast) => toast.id !== id));
}

如何使用:

<script>
  import Toasts from '@/components/Toast/Toasts.svelte';
  import {addToast} from '@/components/Toast/toastStore.js';
  const handleToast = () => {
    addToast('hello world')
  }
</script>
<div class="p-4 bg-gray-600 w-1/2 rounded text-white mx-auto active:opacity-70" on:click={handleToast}>消息提示</div>

image.png

移动端调试神器 vconse

安装vite-plugin-vconsole:

yarn add vite-plugin-vconsole -D
// vite.config.js
import { viteVConsole } from 'vite-plugin-vconsole';
export default defineConfig(({command, mode}) => {
  // console.log(command, mode)
  return {
    plugins: [
      svelte(),
      viteVConsole({
        entry: [path.resolve('src/main.js')], // entry for each page, different from the above
        localEnabled: command === 'serve',
        enabled: command === 'serve',
        config: {
          maxLogNumber: 1000,
          theme: 'dark'
        }
      })
    ],
    ...
  }
})

其他

用vscode开发项目,下载插件Svelte 3 Snippets,Svelte Auto Import,Svelte for VS Code,定会事半功倍!

还有可能遇到的一个小问题,在style标签处可能会提示一个红线错误,这时你查看错误信息找到对应的包的地址,我的是/Users/finget/.vscode/extensions/svelte.svelte-vscode-105.16.0,进入这个目录,安装一下less就好了。

image.png

感受

  • 个人感觉Svelte的语法和VueReact有很多相似之处,对于熟悉VueReact的同学,上手难度不大。

  • 编译速度上,Vite+Svelte是真的快,几乎同等代码量(初始化+几个简单的页面)的情况下,比Vite+Vue3 快的多。

image.png image.png

  • Svelte最大缺点就是社区不够强大,使用人数不多,容易踩坑,希望能越来越好!但是作为开发一些官网呀,博客,H5活动页的项目,用起来还是得心应手,值得大家尝试!

文中Demo代码地址: github.com/FinGet/vite…