如何最好地将 scss 文件中引用的资产(图像和字体)包含在汇总包中

Mah*_*hus 10 rollup postcss rollupjs storybook

我正在编写一个带有 typescript、sass 和 rollup 的 react 组件库,我希望它尽可能独立。

有没有人对如何最好地包含 scss 文件中引用的资产(图像和字体)有任何建议?

一种解决方案可能是某种加载程序(例如 postcss 处理器),用 base64 版本替换 scss 文件中引用的所有图像和字体资产。

有没有人有一个例子可以有效地做到这一点?任何解决方案或建议将不胜感激

我的汇总配置如下所示:

import peerDepsExternal from "rollup-plugin-peer-deps-external";
import resolve from "rollup-plugin-node-resolve";
import typescript from "rollup-plugin-typescript2";
import scss from 'rollup-plugin-scss'
import sass from "rollup-plugin-sass";
import commonjs from "rollup-plugin-commonjs";
import copy from "rollup-plugin-copy";
import url from '@rollup/plugin-url';

import packageJson from "./package.json";

export default {
  input: "src/index.tsx",
  output: [
    {
      file: packageJson.main,
      format: "cjs",
      sourcemap: true
    },
    {
      file: packageJson.module,
      format: "esm",
      sourcemap: true
    }
  ],
  plugins: [
    peerDepsExternal(),
    resolve({
      browser: true
    }),
    typescript({ objectHashIgnoreUnknownHack: true }),
    commonjs({
      include: ["node_modules/**"],
      exclude: ["**/*.stories.js"],
      namedExports: {
        "node_modules/react/react.js": [
          "Children",
          "Component",
          "PropTypes",
          "createElement"
        ],
        "node_modules/react-dom/index.js": ["render"]
      }
    }),
    scss({
    }),
    sass({
      insert: true
    }),
    copy({
      targets: [
        {
          src: "src/variables.scss",
          dest: "build",
          rename: "variables.scss"
        },
        {
          src: "src/typography.scss",
          dest: "build",
          rename: "typography.scss"
        },
        {
          src: "src/assets",
          dest: "build/",
        },
      ]
    })
  ]
};
Run Code Online (Sandbox Code Playgroud)

更新:

所以我所做的可能是hacky,但它解决了我的问题。

一个 commonjs 插件之后,我在 rollup.config.js 的 plugins 数组中添加了一个 postcss- plugin。

postcss({
      inject: true,
      plugins: [
        postcssInlineBase64({
          baseDir: 'src/assets/',
        }),
        postcssUrl({
          url: 'inline',
        }),
        atImport({
          path: path.resolve(__dirname, '../'),
        }),
      ],
    }),
Run Code Online (Sandbox Code Playgroud)

我也使用 storybook,它内部使用 webpack,所以我不得不在 .storybook/webpack.config.js 中重新创建相同的:

config.module.rules.push({
    test: /\.scss$/,
    use: [
      'style-loader',
      'css-loader',
      {
        loader: 'postcss-loader',
        options: {
          inject: true,
          ident: 'postcss',
          plugins: [
            postcssInlineBase64({
              baseDir: 'src/assets/',
            }),
            postCssUrl({ url: 'inline' }),
            atImport({
              path: path.resolve(__dirname, '../'),
            }),
          ],
        },
      },
      'sass-loader',
    ],
    include: path.resolve(__dirname, '../'),
  });
Run Code Online (Sandbox Code Playgroud)

现在,当在 scss(或其他地方)中使用 url 指令时,我可以使用以下命令包围任何路径:

b64---<SOME_PATH>---

例如:

@font-face {
  font-family: 'Open Sans';
  font-display: swap;
  font-style: normal;
  font-weight: 300;
  src: url('b64---./fonts/open-sans/open-sans-v15-latin-ext_latin-300.woff2---') format('woff2'),
    url('b64---./fonts/open-sans/open-sans-v15-latin-ext_latin-300.woff---') format('woff');
}
Run Code Online (Sandbox Code Playgroud)

这使得 post css 将资产捆绑为 base64。

对于任何可能遇到这篇文章的人。祝你好运!希望这可以帮助!

ela*_*ado 5

使用 postcss-url asset 函数让它工作,使用真实的图像文件而不是 base64。

这个想法是,包将 CSS 提取到一个单独的文件中,并且所有引用的资源都url()被拦截、散列并放入一个文件夹 ( _assets) 中,然后 postcss-url 将原始 url 更改为该文件夹。

消费者应用程序(例如带有类似工具的 webpack css-loader)导入 CSS

import 'pkg-name/dist/index.css'
Run Code Online (Sandbox Code Playgroud)

其中所有url()s 看起来都像这样background-image: url(_assets/<hash>.png),并且该加载器还负责将这些资源引入包中,并将 替换url()为公共路径的本地 url,例如url(/static/<app-hash>.png)

由于无法从该回调访问插件实例,它不使用内置的汇总emitFile,尽管这是理想的。

import 'pkg-name/dist/index.css'
Run Code Online (Sandbox Code Playgroud)