【问题标题】:Use ContextReplacementPlugin for dynamically setting the resource path in require.context使用 ContextReplacementPlugin 动态设置 require.context 中的资源路径
【发布时间】:2020-05-21 07:57:22
【问题描述】:

我想从两个文件夹“NL”和“JP”导入帖子。并为此使用动态设置的文件夹。

当我静态编写文件夹时,它可以工作:

import { useState, useEffect } from 'react';
import importAllMarkdown from '../importAllMarkdown';
import { Data, PostBlog } from '../shared.types';

type countryCode = 'NL' | 'JP';

function usePosts(countryCode: countryCode): Data<PostBlog>[] | null {
  const [posts, setPosts] = useState<Data<PostBlog>[] | null>(null);

  useEffect(() => {

    // this codeblock for each country :(
    if (countryCode === 'NL') {
      const importedPosts: Data<PostBlog>[] = 
        importAllMarkdown(require.context('../posts/NL', true, /\.md$/));

      setPosts(importedPosts);
    }

    if (countryCode === 'JP') {
      const importedPosts: Data<PostBlog>[] =
        importAllMarkdown(require.context('../posts/JP', true, /\.md$/));

      setPosts(importedPosts);
    }
  }, [countryCode, setPosts]);

  return posts;
}

export default usePosts;

正如您在此示例中所见,对于每个国家/地区,您必须添加一个完整的块来导入该文件夹中的文件。

当您动态设置文件夹时:

const folderPath = `../posts/${countryCode}`;
const importedPosts: Data<PostBlog>[] = 
  importAllMarkdown(require.context(folderPath, true, /\.md$/));

..它给出了错误:TypeError: __webpack_require__(...).context is not a function.

现在从这个Github thread看来ContextReplacementPlugin可以用于动态设置文件夹。

"另一种方法是使用 require(variable) 并使用 ContextReplacementPlugin 通过 config 提供“静态性”。在这种情况下,您需要在插件的参数中指定变量的所有可能值(或抓取一个目录)。”

所以我正在尝试:

./next.config.js

module.exports = {
  webpack(config, { webpack }) {
    config.plugins.push(new webpack.ContextReplacementPlugin(
      /^\..\/posts/,
      /NL|JP/,
    ));
    return config;
  },
};

这仍然会产生错误:TypeError: __webpack_require__(...).context is not a function

出了什么问题?

【问题讨论】:

  • 你找到解决方案了吗?
  • 有点。添加了一个答案。希望这对您的问题也有帮助。
  • 谢谢,我确实做了类似的事情。

标签: webpack next.js


【解决方案1】:

原来在require.context 中不能使用变量作为参数。此问题的错误消息有点不清楚。但是the documentation 声明:“传递给 require.context 的参数必须是文字!”

这可以通过查询整个文件夹然后根据您需要的结果过滤结果来解决。

在上面的例子中是:

// needed to separate the posts based on the country
const byCountry = (post: Data<PostBlog>, countryCode: countryCode): boolean => post.slug.split('/')[1] === countryCode;

function usePosts(countryCode: countryCode): Data<PostBlog>[] | null {
  const [posts, setPosts] = useState<Data<PostBlog>[] | null>(null);

  useEffect(() => {
    const importedPosts: Data<PostBlog>[] = importAllMarkdown(require.context('../posts', true, /\.md$/));
    const onlyCurrentCountryPosts = importedPosts.filter((post) => byCountry(post, countryCode));
    const sortedCurrentCountryPosts = onlyCurrentCountryPosts.sort(byDate).reverse();

    setPosts(sortedCurrentCountryPosts);
  }, [countryCode, setPosts]);

  return posts;
}

export default usePosts;

但是这有点低效。对于每个 usePosts 调用,它都会查询所有帖子,然后返回一个小节。

【讨论】:

    猜你喜欢
    • 2013-02-09
    • 1970-01-01
    • 1970-01-01
    • 2016-01-23
    • 2014-02-09
    • 1970-01-01
    • 1970-01-01
    • 2023-03-04
    • 2022-01-02
    相关资源
    最近更新 更多