乐趣区

关于svelte:FESRCsvelte的tsscss生产环境实践指南

简介

Svelte 是最近新出的前端框架,和 react 的 vdom 不同,Svelte 应用动态剖析在构建时创立 DOM 更新代码,搭配官网高深莫测的老手教程,给人直观的应用体验,上手会很快。在业务实际中我上手采坑并总结了一下内容,经实际能够间接上生产。

ts+scss+svlete 模板

通常在 react 我的项目里咱们会用 ts 进步业务逻辑开发效率,style module 用来防止 css 命名重叠。在 react 中可能是这么写

// index.tsx
...
<ul className={styles.mylist} ref={this.myRef} onScroll={this.scrollHandler}>
{this.props.data.length>0
 ?this.props.data.map((v,i)=>
    <Item key={i}>{v}</Item>
 )
 :<li>empty</li>
 }
</ul>
...

在 svelte 间接单文件组件

// index.svelte
<script lang="ts">
...
import type {IData} from "./types.ts"
import Item from "./item.svelte"
export let data:IData=[]
export let myRef;
scrollHandler=()=>{}
</script>
<style>
...
</style>

<ul class="mylist" bind:this={myRef} on:scroll={scrollHandler}>
{# if data.length>0}
    <li>empty</li>
{:else}
    {#each data as v,i}
        <Item>{v}</Item>
    {/each}
{/if}
</ul>

须要留神:
1. 但凡 svelte 组件 import 的名称必须首字母大写,不然编译不认它是个 svelte 组件。

2.import ts 类型申明必须是 import type … 也是为了更好的辨别.

  1. export let/const 变量 作为相似 props 的语法,目前语法查看还不欠缺,有时会呈现正告
  2. 和 React 不同,循环的 dom 不强制查看 key 属性
  3. svelte 单文件组件中的 css 会人造反对编译成类 style module 的 className,不必放心 css 名称反复,但会疏忽和正告未应用的 css,不会打包进去。(这个很奇怪,如果父组件和子组件想笼罩对方的 css classname 就比拟麻烦了,这时候纯 css 思路断了只能换 js 思路也就是通过 props 来实现)

状态治理

组件内的状态没什么好说的,长期变量一把梭就好了。本文只探讨 store 的用法。为了让 svelte 状态治理有 redux 的滋味,我实际中用以下的写法,不喜勿喷:

//store.ts
import {writable} from 'svelte/store';
// 申明初始 state
let initState={
    loading:false,
    readed:0,
}
const state = writable(initState);
const {subscribe, set, update} = state;
// 可能用失去的 reset
const reset = () => set(initState);
//mounted 办法会在组件的 onMount 时调用
const mounted = async () => {updateLoadStart();
    const {data,error}=await server.getPageData();
    !error && await updateReaded(data);
    updateLoadEnd();}
updateLoadStart=()=>update((prevState)=>{
    return {
        ...prevState,
        loading:true
    }
})
...

在组件里便能够这么引入应用:

<script lang="ts">
  import {state,mounted, onBtnClick} from "./store";
onMount(mounted);
</script>

<button on:click={onBtnClick}>{$state.readed}</button>

实际中你能够大胆的拆分和命名 比方类 vue 的命名 mounted method compute 的数据管理,又比方类 rematch 的 select loading.effects 组合,具体看之前框架的习惯适度一下~

须要留神:

  1. 目前没有 devtool 的浏览器插件能够查看批改 state, 我反正装置了个 svelte 的插件试了啥都没有,可能将来不久会公布吧。目前只能 {@debug $state} 来察看 state 的变动

与 dom 的交互

我看到 https://css-tricks.com/lazy-l… 一步步教学写个图片懒加载的组件。着实不错,改一下兼容问题能够上生产。

其次官网文档的 motion/transition/animate 我试过能够很不便实现一些常见动画性能,比方动画折叠开展、轮播的滚动,这里就不贴代码了,跟着文档走一遍根本没难度。

留神的点:
1.on:click 这种间接透传事件的貌似只在组件的根元素起作用,在子元素里还是得用 on:click={() => dispatch(‘click’)} 的形式向上 emit
2.html 标签校验居然认为 href=”javascript:” 不是非法的链接,必须要在上一行正文 <!– svelte-ignore a11y-invalid-attribute –> 才行
3. 款式写法习惯上 class=”” style=”” 更靠近 vue,而不是 react 的 className=”” style={}
4.bind 过的 ref 记得 onDestory 时销毁

打包

官网给的 rollup 打包配置过于简略了,也不兼容 es5。网上看到有其他同学从新编译 svelte 到 es5 的,也是厉害。其实魔改一下官网的 rollup 配置就行。我实际中能够欢快的把 ts 编译成 es5。

简略讲一下几个要点,最初会放出配置文件给大家参考,少走弯路少采坑。

1. 打包资源加 hash

...
output:{
    ...
    entryFileNames: "bundle.[hash].js"
}
  1. 向下兼容

“> 1%, not dead” 为了兼容连箭头语法都不反对的浏览器,抉择个,文件体积会加倍,一个页面差不多 200k gzip 60k
“> 5%, not dead” 这个就小了好多 100k+ gzip 30k+

3. 用 ”rollup-plugin-serve” 换掉官网手写的 serve

!production && serve({
    contentBase: "dist",
    port: 5000
})
  1. svelte css 加 hash
css: (css) => {const hash = crypto.createHash("md5").update("bundle" + css.code).digest("hex");
    css.write("bundle." + hash.slice(0, 8) + ".css", !production);
}

当然如果想 postcss autofixer 进一步解决的网上也有其余答案

5. 用 @rollup/plugin-html 依据模板替换 hash 的文件并生成 manifest

html({
dest: "dist",
fileName: "index.html",
template: async ({bundle}) => {let bundleFileNames = Object.keys(bundle);
    fs.writeFile('dist/asset-manifest.json', JSON.stringify(bundleFileNames.reduce((assetMap,fileName) => {assetMap[fileName.replace(/\.\w+\./, '.')] = fileName;
            return assetMap
    }, {}),null,"\t"),"utf8");
    return bundleFileNames.reduce((code, fileName) =>
            code.replace(fileName.replace(/\.\w+\./, '.'), fileName),
        await fs.readFile("public/index.html", "utf8")
    );
},
})

rolllup.config.js

集体感悟

感觉 svelte 体验上模板语法和单位件组件的思路更靠近 vue,但又不齐全遵循指令标准(比方循环判断)退出了精简但又实用的 动画 和 状态治理。其次性能方面比 react 好一点点,打包体积小是有很大劣势。冀望将来在开发体验比方工具链上有新的冲破。

框架比照?

https://medium.com/@d_kzlv/yeah-holy-wars-i-like-that-1406eb291331 发现 medium 大家意见不一,看看就好

退出移动版