【问题标题】:Next.js DOMPurify.sanitize() shows TypeError: dompurify__WEBPACK_IMPORTED_MODULE_6___default.a.sanitize is not a functionNext.js DOMPurify.sanitize() 显示 TypeError: dompurify__WEBPACK_IMPORTED_MODULE_6___default.a.sanitize is not a function
【发布时间】:2021-04-15 03:57:24
【问题描述】:

我在dangerouslySetInnerHTML={{}} 中使用DOMPurify.sanitize() 来显示从数据库返回的innerHtml。出于最初的目的,我在此页面上使用 getServersideProps()next-redux-wrapper

我用:npm i -S dompurify 安装了 dompurify,目前的版本是:“^2.2.6”。

我的代码:

    import DOMPurify from 'dompurify';
    import { useSelector } from 'react-redux';
    import { END } from 'redux-saga';
    import wrapper from '../redux/storeSetup';

    const EmployeePage = () => {
    
        const blog = useSelector(state => state.data);

        const html_body = blog[0].body_html;
    
        const clean = DOMPurify.sanitize(html_body);
    
        return(
           <div className="mainContainer">
                <div dangerouslySetInnerHTML ={{ __html: clean }} />
                <ul>
                    {blog.map((item) => (
                        <li key={item.author}>
                            <span>{item.author}</span><br/>
                            <span>{item.title}</span>
                            <h4>{item.body_delta}</h4>
                            <p>{item.body_html}</p>
                            <p>{item.created_on}</p>
                        </li>
                    ))}
                </ul>
            </div>
        );
    }

    export const getServerSideProps = wrapper.getServerSideProps( async ({store}) => {
        store.dispatch({type: GET_DATA});
        store.dispatch(END);
        await store.sagaTask.toPromise();    
    });
    export default EmployeePage;

但是当我使用npm run dev 运行它时,我收到了这个错误: TypeError: dompurify__WEBPACK_IMPORTED_MODULE_1___default.a.sanitize is not a function.

这里有什么问题?我尝试使用更简单的代码,但一切都显示相同的错误!我做错了什么?

【问题讨论】:

    标签: javascript next.js server-side-rendering dompurify


    【解决方案1】:

    据此: https://github.com/cure53/DOMPurify/issues/29#issuecomment-466626162

    尝试以下操作(来自上面的示例):

    import { JSDOM } from 'jsdom'
    import DOMPurify from 'dompurify'
    const { window } = new JSDOM(html_body);
    const domPurify = DOMPurify(window);
    console.log(domPurify.sanitize(html_body));
    

    【讨论】:

    • 安装 jsdom 并运行,显示如下:Module not found: Can't resolve 'child_process'!
    • jsdom 方法是否可用于生产?
    • 此解决方案仅用于服务器端的清理。如果你也尝试在浏览器中运行它,它会给你一个错误。
    【解决方案2】:

    我找到了一个可行的解决方案:我不必在服务器端清理 innerHtml,而是在提交富文本博客后立即在客户端对其进行清理,在我的例子中,react-quill

    import dynamic from 'next/dynamic'
    import {useState} from 'react'
    import DOMPurify from 'dompurify';
    
    const QuillNoSSRWrapper = dynamic(import('react-quill'), {
        ssr: false,
        loading: () => <p>Loading...</p>,
    })
    
    // quill modules definitions
    //...
    
    export default function articles() {
        const [text, setText] = useState(preData);
    
        function handleTextChange(content, delta, source, editor) {
            //let str = JSON.stringify(editor.getContents());
            //let parsed = JSON.parse(str)
            setText(editor.getContents());
            const cleaned = DOMPurify.sanitize(editor.getHTML());
            console.log('Cleaned Html: ', cleaned);
    
        return (
            <div className="quill_container">
                <div id="editor" className="editor">
                    <QuillNoSSRWrapper
                        id="quilleditor"
                        modules={modules}
                        formats={formats}
                        theme="snow"
                        value={text}
                        onChange={handleTextChange}
                      />
                 </div>
            </div>
        );
    };
    

    【讨论】:

      【解决方案3】:

      使用Isomorphic dompurify

      可以在服务器端和浏览器上渲染

      【讨论】:

        【解决方案4】:

        昨天在设置 TypeScript/React 时遇到了这个问题。

        import DOMPurify from 'dompurify';
        
        export const sanitize = (html: string): string => DOMPurify.sanitize(html);
        

        此代码在 Jest 测试中完美运行,但在浏览器中失败,因为未定义 DOMPurify 对象。 挖掘后,我发现在窗口范围内附加了一个 DOMPurify 对象。我最终不得不放置一个 hack 来处理在节点和浏览器中运行之间的不同行为:

        import DOMPurify from 'dompurify';
        
        interface IDOMPurifyWindow extends Window {
            DOMPurify: typeof DOMPurify;
        }
        const purify =
            ((window as unknown) as IDOMPurifyWindow)?.DOMPurify || DOMPurify;
        
        export const sanitize = (html: string): string => DOMPurify.sanitize(html);
        

        有一个编译器警告,但它可以正常工作。 我可以通过直接导入库的 es.js 版本来消除编译器警告:import DOMPurify from 'dompurify/dist/purify.es.js'; 但这导致 Jest 无法运行,因为它需要 vanilla JavaScript。

        这个库做得很好,但如果你使用 TypeScript 并在浏览器中运行,它的使用不是很友好。

        【讨论】:

          【解决方案5】:

          我只是切换到js-xss 并制作了一个这样的组件:

          import React from "react";
          import xss from "xss";
          
          const Html = ({ unsafeHtml }: {unsafeHtml: string}): JSX.Element => {
            return (
              <div
                {...props}
                dangerouslySetInnerHTML={{
                  __html: xss(unsafeHtml),
                }}
              />
            );
          };
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-06-24
            • 1970-01-01
            • 2020-01-29
            • 2021-01-21
            相关资源
            最近更新 更多