使用 webpack 时解析 scss 文件中的字体路径

Posted

技术标签:

【中文标题】使用 webpack 时解析 scss 文件中的字体路径【英文标题】:resolving font path in scss file when using webpack 【发布时间】:2018-01-21 03:26:49 【问题描述】:

我在我的 asp.net mvc 核心项目中使用 webpack。我能够捆绑js文件。但我无法解析我的字体路径。

我有这个我是 scss 文件:

$font-path: '../fonts' !global; 

/*fonts*/
/* roboto-300 - latin */
@font-face 
    font-family: 'Roboto';
    font-style: normal;
    font-weight: 300;
    src: url('#$font-path/roboto-v15-latin-300.eot'); /* IE9 Compat Modes */
    src: local('Roboto Light'), local('Roboto-Light'), url('#$font-path/roboto-v15-latin-300.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
    url('#$font-path/roboto-v15-latin-300.woff2') format('woff2'), /* Super Modern Browsers */
    url('#$font-path/roboto-v15-latin-300.woff') format('woff'), /* Modern Browsers */
    url('#$font-path/roboto-v15-latin-300.ttf') format('truetype'), /* Safari, android, ios */
    url('#$font-path/roboto-v15-latin-300.svg#Roboto') format('svg'); /* Legacy iOS */

文件结构:

└── Project
    ├── assets
    │ └── scripts
    │   └── main.ts
    │ └── scss
    │   └── fonts
    │       └── roboto-condensed-v13-latin-700.eot
    │   └── main.scss
    │
    └── webpack.config.js

var path = require('path');
var extractTextPlugin = require("extract-text-webpack-plugin");
var cleanWebpackPlugin = require('clean-webpack-plugin');
var webpack = require('webpack');

module.exports = 
    entry: 
        'role/role': './assets/scripts/role/roleVM.ts',
        main: './assets/scripts/main.ts',
        vendor: ["bootstrap", "popper.js", "jquery"]
    ,
    output: 
        filename: 'js/[name].js',
        path: path.resolve(__dirname, 'wwwroot/dist/')
    ,
    module: 
        rules: [
            
                test: /\.tsx?$/,
                loader: 'ts-loader',
                exclude: /node_modules/,
            ,
            
                test: /\.scss$/,
                use: extractTextPlugin.extract(
                    use: [
                        loader: "css-loader", options: 
                            sourceMap: true
                        
                    , 
                        loader: "resolve-url-loader"
                    ,
                    
                        loader: "sass-loader", options: 
                            sourceMap: true
                        ,

                    ],
                    fallback: 'style-loader'
                ),
                exclude: /node_modules/
            ,
            
                test: /.(ttf|otf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/,
                use: [
                    loader: 'file-loader',
                    options: 
                        name: '[name].[ext]',
                        outputPath: 'fonts/'
                    
                ]
            
        ]
    ,
    plugins: [
        new cleanWebpackPlugin(['dist'], 
            root: path.resolve(__dirname, 'wwwroot'),
            verbose: true,
            dry: false
        ),
        new webpack.optimize.CommonsChunkPlugin( name: 'vendor', filename: 'js/vendor.js' ),
        new extractTextPlugin("./css/main.css"),
        new webpack.ProvidePlugin(
            $: 'jquery',
            jQuery: 'jquery',
            'window.jQuery': 'jquery',
            'Popper': 'popper.js'
        )
    ],
    resolve: 
        extensions: [".tsx", ".ts", ".js", '.scss'],
        modules: [
            path.resolve('./'),
            path.resolve('./node_modules'),
        ]
    
;

当我构建 webpack 时,我得到一个错误:

./node_modules/css-loader 中的错误?"sourceMap":true!./node_modules/resolve-url-loader!./node_modules/sass-loader/lib/loader.js?"sourceMap":真的!./assets/scss/main.scss 找不到模块:错误:无法解析“../fonts/roboto-condensed-v13-latin-700.eot” 'C:\project\src\project\assets\scss' @ ./node_modules/css-loader?"sourceMap":true!./node_modules/resolve-url-loader!./node_modules/sass-loader/lib/loader.js?"sourceMap":true!. /assets/scss/main.scss 6:215433-215491

【问题讨论】:

看起来您应该使用 1 点而不是 2 作为字体路径:$font-path: './fonts' !global; 如果它位于 scss 文件夹中的 .scss 文件中,则字体是相对的子文件夹对此,与其父级无关。 不,我已经试过了,没用。 你能显示只有1个点发生的错误吗? 【参考方案1】:

您可以尝试添加以下两个选项吗?

    将 entry.devtool 选项添加到您的 webpack 配置中。

    ExtractTextPlugin 有一个可以解决此问题的 publicPath 选项。

    module.exports = 
    entry: 
        'role/role': './assets/scripts/role/roleVM.ts',
        main: './assets/scripts/main.ts',
        vendor: ["bootstrap", "popper.js", "jquery"]
    ,
    output: 
        filename: 'js/[name].js',
        path: path.resolve(__dirname, 'wwwroot/dist/')
    ,
    devtool:'source-map', //..1. add devtool option to source-map
    module: 
        rules: [
            
                test: /\.tsx?$/,
                loader: 'ts-loader',
                exclude: /node_modules/,
            ,
            
                test: /\.scss$/,
                use: extractTextPlugin.extract(
                    publicPath:'',
                    //2. add public path to your font folder in the build directory
                    use: [
                        loader: "css-loader", options: 
                            sourceMap: true
                        
                    , 
                        loader: "resolve-url-loader"
                    ,
                        
                            loader: "sass-loader", options: 
                            sourceMap: true
                        ,
    
                        ],
                    fallback: 'style-loader'
                ),
                exclude: /node_modules/
            ,
            
                test: /.(ttf|otf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/,
                use: [
                    loader: 'file-loader',
                    options: 
                        name: '[name].[ext]',
                        outputPath: 'fonts/'
                    
                ]
            
        ]
    ,
    plugins: [
        new cleanWebpackPlugin(['dist'], 
            root: path.resolve(__dirname, 'wwwroot'),
            verbose: true,
            dry: false
        ),
        new webpack.optimize.CommonsChunkPlugin( name: 'vendor', filename: 'js/vendor.js' ),
        new extractTextPlugin("./css/main.css"),
        new webpack.ProvidePlugin(
            $: 'jquery',
            jQuery: 'jquery',
            'window.jQuery': 'jquery',
            'Popper': 'popper.js'
        )
    ],
    resolve: 
        extensions: [".tsx", ".ts", ".js", '.scss'],
        modules: [
            path.resolve('./'),
            path.resolve('./node_modules'),
        ]
    
    

    ;

【讨论】:

有没有办法不发出字体文件?忽略来自 node_module dep 的 sass 文件字体?

以上是关于使用 webpack 时解析 scss 文件中的字体路径的主要内容,如果未能解决你的问题,请参考以下文章

Webpack 中的相对 CSS url

SCSS 文件在使用 Webpack 做出反应时未编译为 CSS

Webpack - resolve-url-loader 无法正确解析路径

如何将scss预编译为webpack中的单个css文件?

Webpack 4 - 如何解析不同的 img URL

使用 Webpack 4 和 react js 在 scss 中导入字体或图像文件时出错