首页 > 解决方案 > 如何使用 sass 为自定义 npm 包加载带有 webpack 的本地字体?

问题描述

背景:

为了或可重用性,我正在编写一个 NPM 包来存储样式化的反应组件。

我已经对组件进行了大部分样式化,但无法让那些继承存储在本地 npm 包中的正确字体。

NPM项目的文件夹结构:

Webpack.config.js

var path = require('path');
const sass = require("node-sass");
const sassUtils = require("node-sass-utils")(sass);
const sassVars = require(__dirname + "/src/styles/theme.js");
const ExtractTextPlugin = require("extract-text-webpack-plugin");

// Convert js strings to dimenssions
const convertStringToSassDimension = function(result) {
  // Only attempt to convert strings
  if (typeof result !== "string") {
    return result;
  }

  const cssUnits = [
    "rem",
    "em",
    "vh",
    "vw",
    "vmin",
    "vmax",
    "ex",
    "%",
    "px",
    "cm",
    "mm",
    "in",
    "pt",
    "pc",
    "ch"
  ];
  const parts = result.match(/[a-zA-Z]+|[0-9]+/g);
  const value = parts[0];
  const unit = parts[parts.length - 1];
  if (cssUnits.indexOf(unit) !== -1) {
    result = new sassUtils.SassDimension(parseInt(value, 10), unit);
  }

  return result;
};

const dist = path.resolve(__dirname, 'dist');
const app = path.resolve(__dirname, 'src');

module.exports = {
  mode: 'production',
  entry: './src/index.js',
  output: {
    path: dist,
    filename: 'index.js',
    libraryTarget: 'commonjs2' // THIS IS THE MOST IMPORTANT LINE! :mindblow: I wasted more than 2 days until realize this was the line most important in all this guide.
  },
  module: {
    rules: [
      // Javascript file loading
      {
        test: /\.js$/,
        include: app,
        exclude: /(node_modules|bower_components|dist)/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['env']
          }
        }
      },
      {
        test: /\.(scss|sass)$/,
        use: ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: [
            { loader: 'css-loader' },
            {
              loader: "sass-loader?sourceMap",
              options: {
                functions: {
                  "get($keys)": function(keys) {
                    keys = keys.getValue().split(".");
                    var result = sassVars;
                    var i;
                    for (i = 0; i < keys.length; i++) {
                      result = result[keys[i]];
                      // Convert to SassDimension if dimenssion
                      if (typeof result === "string") {
                        result = convertStringToSassDimension(result);
                      } else if (typeof result === "object") {
                        Object.keys(result).forEach(function(key) {
                          var value = result[key];
                          result[key] = convertStringToSassDimension(value);
                        });
                      }
                    }
                    result = sassUtils.castToSass(result);
                    return result;
                  }
                }
              },
            },
          ],
        })
      },
      {
        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: 'fonts/[name].[ext]'
        }
      }
    ]
  },
  plugins: [
    new ExtractTextPlugin({ filename: '[name].css' })
  ]
};

src/index.js

import Header1 from './elements/Header1';
import Header2 from './elements/Header2';
import Header3 from './elements/Header3';
import Toggle from './elements/Toggle';

module.exports = {
  Header1,
  Header2,
  Header3,
  Toggle,
};

src/elements/Header1.js

import styled from 'styled-components';
import * as theme from '../styles/theme';
import '../styles/variables.scss';

const Header1 = styled.h1`
  font-family: brownprott;
  font-weight: bold;
  font-size: 32px;
  color: ${theme.colors.teal};
`;

export default Header1;

src/styles/variables.scss

@import 'typography.scss';

$colors: get("colors");

$white: #FFFFFF;
$teal: #00EBD0;
$lightGrey: #DADCDD;
$darkGrey: #222425;
$red: #FF0000;
$info: #1FB6FF;
$success: #13CE66;
$danger: #FF4949;
$warning: #FFC82C;

src/styles/typography.scss

$font_path: '~/assets/fonts/';

@font-face {
  font-family: "brownprott";
  src: url($font_path + "brownprott_light.ttf");
  font-weight: "lighter";
}

@font-face {
  font-family: "brownprott";
  src: url($font_path + "brownprott_regular.ttf");
  font-weight: "normal";
}

@font-face {
  font-family: "brownprott";
  src: url($font_path + "brownprott_italic.ttf");
  font-weight: "normal";
  font-style: "italic";
}

@font-face {
  font-family: "brownprott";
  src: url($font_path + "brownprott_bold.ttf");
  font-weight: "bold";
}

现在,当我运行时,webpack --watch我得到以下输出:

@npm-module-name@0.0.2 开始 /path/to/npm-module-name webpack --watch

Webpack is watching the files…

Hash: 549baa5760d8010ca491
Version: webpack 4.8.3
Time: 1148ms
Built at: 2018-05-25 11:29:58
   Asset       Size  Chunks             Chunk Names
index.js   55.7 KiB       0  [emitted]  main
main.css  504 bytes       0  [emitted]  main
Entrypoint main = index.js main.css
 [2] ./src/styles/theme.js 373 bytes {0} [built]
[11] ./src/elements/Toggle.js 4.42 KiB {0} [built]
[12] ./src/elements/Header3.js 1.17 KiB {0} [built]
[13] ./src/elements/Header2.js 1.17 KiB {0} [built]
[21] (webpack)/buildin/harmony-module.js 597 bytes {0} [built]
[23] ./src/elements/Header1.js 1.16 KiB {0} [built]
[24] ./src/index.js 630 bytes {0} [built]
[28] ./node_modules/css-loader!./node_modules/sass-loader/lib/loader.js??ref--5-3!./src/styles/variables.scss 712 bytes [built]
[29] ./src/styles/variables.scss 41 bytes [built]
    + 21 hidden modules
Child extract-text-webpack-plugin node_modules/extract-text-webpack-plugin/dist node_modules/css-loader/index.js!node_modules/sass-loader/lib/loader.js??ref--5-3!src/styles/variables.scss:
    Entrypoint undefined = extract-text-webpack-plugin-output-filename
    [1] ./node_modules/css-loader!./node_modules/sass-loader/lib/loader.js??ref--5-3!./src/styles/variables.scss 712 bytes {0} [built]
        + 1 hidden module

并生成以下文件:

当我将此 npm 包导入我的另一个项目时,我得到:

使用此自定义 npm 包的应用程序的控制台日志

关于如何确保我正在处理的项目能够成功加载 NPM 包中的字体并让那些通过使用的项目看到的字体的任何帮助/说明,那就太好了!

谢谢你。

标签: reactjsnpmwebpackfontsstyled-components

解决方案


推荐阅读