FE.SRC-svelte的ts+scss生產環境實踐指南

image.png

簡介

Svelte是最近新出的前端框架,和react的vdom不一樣,Svelte使用靜態分析在構建時建立DOM更新代碼,搭配官網一目瞭然的新手教程,給人直觀的使用體驗,上手會很快。在業務實踐中我上手採坑並總結了一下內容,經實踐能夠直接上生產。javascript

ts+scss+svlete模板

一般在react項目裏咱們會用ts提升業務邏輯開發效率,style module用來避免css命名重疊。在react中多是這麼寫css

// 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直接單文件組件html

// 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 ... 也是爲了更好的區分.vue

  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的味道,我實踐中用如下的寫法,不喜勿噴:java

//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
    }
})
...

在組件裏即可以這麼引入使用:react

<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 組合,具體看以前框架的習慣過分一下~json

須要注意:redux

  1. 目前沒有devtool的瀏覽器插件能夠查看修改state,我反正安裝了個svelte的插件試了啥都沒有,可能將來不久會發布吧。目前只能{@debug $state} 來觀察state的變化

與dom的交互

我看到 https://css-tricks.com/lazy-l... 一步步教學寫個圖片懶加載的組件。着實不錯,改一下兼容問題能夠上生產。segmentfault

其次官方文檔的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你們意見不一,看看就好

相關文章
相關標籤/搜索