为什么ssr老是报错? —— ssr与依赖库的规范

199 阅读2分钟

总结

  1. 依赖库不规范 (package.json的main值指向了esm代码)

    webpack中, module值应该指向esm代码, 而main值应该指向commonjs代码, 如果没有commonjs代码, main值就不应该填写, 这样会导致webpack将esm代码当作commonjs代码处理, 导致本来应该自动编译出一份commonjs代码的, 也不会生效.

    比如lodash-es这个库, 只有esm代码, 但是package.json中的main值也填了...

  2. 代码使用不规范 (module/esm/xxx)

    如果二级依赖库本身就存在commonjs, 比如是/lib路径, 那么在一级依赖库中就应该直接module/lib/xxx, module/esm/xxx只会导致强行使用esm代码而报错. 那如果是二级依赖库没有commonjs代码, 且需要带路径导入(module/esm/xxx), 那么可能需要其他的特殊配置, 或者导致使用了module/esm/xxx的这个文件, 不能正常ssr, 需要动态导致才能使用.

    二级依赖库: 项目依赖于module1这个库, 这个库就叫一级依赖库, module1依赖于module2, 这个库就叫二级依赖库.

    如果这个依赖库是你自己把握的, 那可以把所有需要外部导入使用的函数或者组件, 直接从根目录导出.

  3. ssr时使用了node端不存在的对象 (document、window等) 用typeof window === 'undefined'判断即可, 如

    export const task = () => {
        if (typeof window === 'undefined') return;
        // do something...
    };
    

    或者组件 (这里用react代码, vue也是同一个思路)

    export const Comp = () => {
        // 下面的代码会导致水合错误提示, 虽然功能可以正常使用
        // if (typeof window === 'undefined') return null;
        // 用useIsBrower会更好
        const isBrowser = useIsBrower();
        if (!isBrowser) return null;
        return (
            <div>Comp</div>
        );
    };
    
    // useIsBrower的实现
    import { useState } from 'react';
    const useIsBrower = () => {
        const [isBrowser, setIsBrowser] = useState(false);
        useEffect(() => {
            setIsBrowser(true);
        }, []);
        return isBrowser;
    };