Sveltekit:找不到模块 'swiper'

Sveltekit: Cannot find module 'swiper'

我尝试了 sveltekit-swiper 示例 https://swiperjs.com/svelte

08:07:51 [vite] Error when evaluating SSR module /src/routes/s.svelte: Error: Cannot find module 'swiper' from 'C:/Svelte/tw09swipe/src/routes'
    at Function.resolveSync [as sync] (C:\Svelte\tw09swipe\node_modules\resolve\lib\sync.js:102:15)
    at resolveFrom (C:\Svelte\tw09swipe\node_modules\vite\dist\node\chunks\dep-9f74b403.js:4081:29)
    at resolve (C:\Svelte\tw09swipe\node_modules\vite\dist\node\chunks\dep-9f74b403.js:75136:22)
    at nodeRequire (C:\Svelte\tw09swipe\node_modules\vite\dist\node\chunks\dep-9f74b403.js:75115:25)
    at ssrImport (C:\Svelte\tw09swipe\node_modules\vite\dist\node\chunks\dep-9f74b403.js:75057:20)
    at eval (/src/routes/s.svelte:7:37)
    at async instantiateModule (C:\Svelte\tw09swipe\node_modules\vite\dist\node\chunks\dep-9f74b403.js:75100:9)

我已经安装了新的 sveltekit 和 swiper。版本:

swiper@7.0.4
vite@2.5.6
@sveltejs/kit@1.0.0-next.165

可以在 codesandbox 中找到 Swiper 7 的工作示例:https://codesandbox.io/s/3dxrg 它使用 Swiper 7.0.3 和 SvelteKit v1.0.0-next.104


我已经安装了 svelte/kit 和 swiper,没有任何更改:

mkdir tw09swipe
cd tw09swipe
npm init svelte@next
npm install
npm i swiper

这是我的 package.json:

{
  "name": "~TODO~",
  "version": "0.0.1",
  "scripts": {
    "dev": "svelte-kit dev",
    "build": "svelte-kit build",
    "preview": "svelte-kit preview",
    "check": "svelte-check --tsconfig ./tsconfig.json",
    "check:watch": "svelte-check --tsconfig ./tsconfig.json --watch"
  },
  "devDependencies": {
    "@sveltejs/kit": "next",
    "svelte": "^3.34.0",
    "svelte-check": "^2.0.0",
    "svelte-preprocess": "^4.9.4",
    "tslib": "^2.0.0",
    "typescript": "^4.0.0"
  },
  "type": "module",
  "dependencies": {
    "swiper": "^7.0.5"
  }
}

这里是 tsconfig.json:

{
    "compilerOptions": {
        "moduleResolution": "node",
        "module": "es2020",
        "lib": ["es2020", "DOM"],
        "target": "es2019",
        /**
            svelte-preprocess cannot figure out whether you have a value or a type, so tell TypeScript
            to enforce using \`import type\` instead of \`import\` for Types.
            */
        "importsNotUsedAsValues": "error",
        "isolatedModules": true,
        "resolveJsonModule": true,
        /**
            To have warnings/errors of the Svelte compiler at the correct position,
            enable source maps by default.
            */
        "sourceMap": true,
        "esModuleInterop": true,
        "skipLibCheck": true,
        "forceConsistentCasingInFileNames": true,
        "baseUrl": ".",
        "allowJs": true,
        "checkJs": true,
        "paths": {
            "$lib": ["src/lib"],
            "$lib/*": ["src/lib/*"]
        }
    },
    "include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.ts", "src/**/*.svelte"]
}

和svelte.config.js:

import preprocess from 'svelte-preprocess';

/** @type {import('@sveltejs/kit').Config} */
const config = {
    // Consult https://github.com/sveltejs/svelte-preprocess
    // for more information about preprocessors
    preprocess: preprocess(),

    kit: {
        // hydrate the <div id="svelte"> element in src/app.html
        target: '#svelte'
    }
};

export default config;

routes/s.苗条

<script>

    // Import Swiper Svelte components    
    import { Navigation, Pagination, Scrollbar, A11y } from "swiper";
    import { Swiper, SwiperSlide } from "swiper/svelte";    

    // Import Swiper styles
    import "swiper/css";
    import "swiper/css/navigation";
    import "swiper/css/pagination";
    import "swiper/css/scrollbar";
</script>

<Swiper
    modules={[Navigation, Pagination, Scrollbar, A11y]}
    spaceBetween={50}
    slidesPerView={3}
    navigation
    pagination={{ clickable: true }}
    scrollbar={{ draggable: true }}
    on:slideChange={() => console.log("slide change")}
    on:swiper={(e) => console.log(e.detail[0])}
>
    <SwiperSlide>Slide 1</SwiperSlide>
    <SwiperSlide>Slide 2</SwiperSlide>
    <SwiperSlide>Slide 3</SwiperSlide>
    <SwiperSlide>Slide 4</SwiperSlide>
    ...
</Swiper>

SvelteKit 有一个解决方法(应该也适用于 Sapper)

Slider.svelte

<script>
    import { Swiper, SwiperSlide } from 'swiper/svelte';
    import SwiperCore, { Mousewheel, Pagination } from 'swiper';
    import 'swiper/css';
    import 'swiper/css/pagination';

    ...

    SwiperCore.use([Mousewheel, Pagination]);
</script>

...
    <Swiper
        direction='vertical'
        mousewheel={true}
        pagination={true}
        slidesPerView={1}
        on:slideChange={onSlideChange}
        on:swiper={(e) => console.log(e.detail[0])}
    >
        <SwiperSlide>
    </Swiper>
...

这是可行的,我们以这种方式导入 Slider.svelte 组件:

<script>
    ...
    let Slider;
    onMount(async () => {
        const module = await import('./components/Slider.svelte');
        Slider = module.default;
    });
    ...
</script>

<svelte:component this={Slider}/>

...

所以我基本上建议不要导入 onMount 中的所有 Swiper 实例,而是导入包含 onMount 中的 Swiper Slider 的组件 - 希望它能帮助别人并让你的代码库更干净: )