使用 Webpack 解析从 node_modules 到 Dist 文件夹的相对路径

Posted

技术标签:

【中文标题】使用 Webpack 解析从 node_modules 到 Dist 文件夹的相对路径【英文标题】:Resolve Relative Path from node_modules to Dist folder with Webpack 【发布时间】:2019-10-15 13:08:15 【问题描述】:

我将 React 组件用作 NPM 包。在组件中,我有 SCSS 文件 使用 url(../iamges/img..) 路径,但实际上,位于 Dist 文件夹中的 images 文件夹,我如何指向 Webpack 从 node_modules 获取相对路径并从位于 Dist 中的 images 文件夹中提供它?

located in node_modules =>
background: url('../images/some-icon.svg') no-repeat center center; 

Webpack 配置:


const webpack = require('webpack');
const path = require('path');

module.exports = 
    entry: './src/index.js',
    devtool: 'inline-module-source-map',
    output: 
        path: path.resolve(__dirname, '/dist'),
        filename: 'bundle.js',
        publicPath: '/',
    ,
    module: 
        rules: [
            
                test: /\.js$/,
                use: 
                    loader: 'babel-loader',
                ,
            ,
            
                test: /\.scss$/,
                use: [
                     loader: 'style-loader' ,
                     loader: 'css-loader' ,
                    
                        loader: 'resolve-url-loader',
                        // options: 
                        //  debug: true,
                        //  root: path.join(__dirname, './dist/images'),
                        //  includeRoot: true,
                        //  absolute: true,
                        // ,
                    ,
                    
                        loader: 'sass-loader',
                        options: 
                            sourceMap: true,
                            sourceMapContents: false,
                        ,
                    ,
                ],
            ,
            
                test: /\.css$/,
                loaders: ['style-loader', 'css-loader'],
            ,
            
                test: /\.(png|jpg|gif|svg|eot|ttf|woff|woff2)$/,
                use: 
                    loader: 'url-loader?name=/images/[name].[ext]',
                    options: 
                        limit: 10000,
                    ,
                ,
            ,
        ],
    ,
    resolve: 
        extensions: ['.js', '.jsx'],
        // modules: [path.resolve(__dirname, '/images'), 'node_modules'],
        alias: 
            'react-redux': path.resolve('./node_modules/react-redux'),
        ,
    ,
    plugins: [new webpack.HotModuleReplacementPlugin()],
    devServer: 
        hot: true,
        publicPath: '/dist/',
    ,
;

babel.config.js

module.exports = 
    // presets: ['@babel/preset-env', '@babel/preset-react'],
    plugins: [
        '@babel/plugin-proposal-class-properties',
        '@babel/plugin-proposal-export-default-from',
        '@babel/transform-runtime',
    ],
    sourceType: 'unambiguous',
    presets: [
        [
            '@babel/preset-env',
            
                targets: 
                    node: 'current',
                ,
            ,
        ],
        '@babel/preset-react',
    ],
;


dist
   -- images
   -- index.html

错误:

ERROR in ./node_modules/comp/src/styles/details.scss (./node_modules/css-loader!./node_modules/resolve-url-loader!./node_modules/sass-loader/lib/loader.js??ref--5-3!./node_modules/compdetails/src/styles/details.scss)
Module not found: Error: Can't resolve '../images/icon.svg'

【问题讨论】:

您查看了吗:***.com/questions/27502608/… 【参考方案1】:

css 中通过url('...') 引用的任何内容都将参考已部署应用程序的路径进行计算(除非未使用变量或函数,否则 scss 不会计算路径):

例如: 如果您引用的组件 SCSS 模块具有 background: url('../images/some-icon.svg') no-repeat center center;

最终的 CSS 编译将是相同的(这也是因为组件没有使用任何 SCSS 变量或函数来计算最终路径)。

因此,您的应用程序将始终尝试以以下方式查找该图像:

例如:http://localhost:3000/../images/some-icon.svg 这是一个问题。 (.. 称为父目录)

如果您尝试使用 http://localhost:3000/sub-url/ 的某些子 URL(也称为子上下文)运行您的应用,并且将图像与 sub-url 文件夹保持平行,它将自动运行。

-- /
   |
   |-- sub-url
         |
         |-- index.html
   |-- images
         |
         |-- some-icon.svg

另一个选项可以用你的覆盖组件 SCSS。

你已经找到了使用resolve-url-loader的解决方案,但是在这种情况下你需要将组件的scss文件导入到你的scss中。

所以你的 webpack 配置 应该是这样的:

const webpack = require('webpack');
const path = require('path');

module.exports = 
    entry: './src/index.js',
    devtool: 'inline-module-source-map',
    output: 
        path: path.resolve(__dirname, '/dist'),
        filename: 'bundle.js',
        publicPath: '/',
    ,
    module: 
        rules: [
            
                test: /\.js$/,
                use: 
                    loader: 'babel-loader',
                ,
            ,
            
                test: /\.scss$/,
                use: [
                     loader: 'style-loader' ,
                     loader: 'css-loader' ,
                    // CHANGE HERE
                    
                        loader: 'resolve-url-loader',
                        options: 
                          root: '/images', // considering all your images are placed in specified folder. Note: this is just a string that will get as prefix to image path
                          includeRoot: true,
                          absolute: true,
                        ,
                    ,
                    
                        loader: 'sass-loader',
                        options: 
                            sourceMap: true,
                            sourceMapContents: false,
                        ,
                    ,

                ],
            ,
            
                test: /\.css$/,
                loaders: ['style-loader', 'css-loader'],
            ,
            
                test: /\.(png|jpg|gif|svg|eot|ttf|woff|woff2)$/,
                use: 
                    loader: 'url-loader?name=/images/[name].[ext]',
                    options: 
                        limit: 10000,
                    ,
                ,
            ,
        ],
    ,
    resolve: 
        extensions: ['.js', '.jsx'],
        // modules: [path.resolve(__dirname, '/images'), 'node_modules'],
        alias: 
            'react-redux': path.resolve('./node_modules/react-redux'),
        ,
    ,
    plugins: [new webpack.HotModuleReplacementPlugin()],
    devServer: 
        hot: true,
        publicPath: '/dist/',
    ,
;

希望对你有帮助。

【讨论】:

以上是关于使用 Webpack 解析从 node_modules 到 Dist 文件夹的相对路径的主要内容,如果未能解决你的问题,请参考以下文章

vuejs:vue-cli webpack模板无法解析sass导入

使用 gulp 从 node_modules 文件夹中使用引导程序(没有 bower 或 webpack)

未找到模块:错误:无法在 webpack.common.js 中解析

webpack - 需要('node_modules/leaflet/leaflet.css')

vuejs:vue-cli webpack 模板无法解析 sass 导入

使用 Angular 7 构建的 Webpack 4 在尝试访问 node_modules 时会出现 sass-loader 问题