Webpack:如何在 .css 中重写 URL

Posted

技术标签:

【中文标题】Webpack:如何在 .css 中重写 URL【英文标题】:Webpack: How to rewrie URL in .css 【发布时间】:2021-09-25 07:11:03 【问题描述】:

连续 3 天我在设置 Webpack 以进行暂存时遇到了麻烦。 目标是在最终的 .css 文件(frontend.css)中重写资产的 url,如下所示:

假设在 .scss 文件中我有:

background: url('/assets/image.png')(这适用于开发和产品)

在最终输出的 .css 文件中,我希望它是:

background: url('https://stage.domain.com/staging/project-name/assets/image.png')

我有脚本npm run stage,用于构建 js。和 .css 仅用于暂存目的。 它在 root 上创建阶段目录,其中包含两个文件 frontened-bundle.js and frontend.css.(参见“文件结构”屏幕截图的底部)。

我尝试使用带有 root 参数的 resolve-url-loader 重写 url,但我无法让它工作。 publicPath 也被忽略。

我不确定我做错了什么。 请指出正确的方向。

文件结构:

webpack.stage.js:

const path = require('path');
    const MiniCssExtractPlugin = require('mini-css-extract-plugin');
    const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
    const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
    const BrowserSyncPlugin = require('browser-sync-webpack-plugin');
    const StyleLintPlugin = require('stylelint-webpack-plugin');
    
    const public_path = 'https://stage.domain.com/staging/project-name/'
    
    module.exports = 
      context: __dirname,
      entry: 
        frontend: [
          './src/js/index.js',
          './src/scss/main.scss'
        ],
        // customizer: './src/customizer.js'
      ,
      resolve: 
        extensions: ['.ts', '.js', '.jsx', '.scss', '...',],
      ,
      output: 
        path: path.resolve(__dirname, 'stage'),
        publicPath: public_path,
        filename: '[name]-bundle.js'
      ,
      mode: 'production',
      // devtool: 'cheap-eval-source-map',
      module: 
        rules: [
          
            enforce: 'pre',
            exclude: /node_modules/,
            test: /\.jsx$/,
            loader: 'eslint-loader'
          ,
          
            test: /\.jsx?$/,
            loader: 'babel-loader'
          ,
          
            test: /\.s?css$/,
            use: [
              
                loader: MiniCssExtractPlugin.loader,
                options: 
                  publicPath: public_path,
                  sourceMap: true
                
              ,
              
                loader: 'css-loader',
                options: 
                  url: false,
                  sourceMap: true
                
              ,
              
                loader: 'resolve-url-loader',
                options: 
                  // root: path.join(__dirname, './'),  // returns url("../../assets/assets/fonts/NewYork.woff2")
                  // root: '/',                         // returns url('../../../../../../assets/fonts/NewYork.woff2')
                  // root: './',                        // returns url('../../assets/fonts/NewYork.woff2')
                  attempts: 1,
                  debug: true,
                  sourceMap: true,
                  publicPath: public_path,
                ,
              ,
              
                loader: 'sass-loader',
                options: 
                  sourceMap: true
                
              ,
            ]
          ,
          
            test: /\.(ttf|woff|woff2|eot|jpe?g|png|svg|gif)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
            use: [
              
                loader: 'file-loader',
                options: 
                  name: '[path][name].[ext]',
                  // outputPath: '../',
                  publicPath: publicPath,
                ,
              ,
              'img-loader',
              'url-loader',
            ]
          
        ]
      ,
      plugins: [
        // new StyleLintPlugin(),
        new MiniCssExtractPlugin(
          filename: '[name].css'
        ),
      ],
      optimization: 
        // minimizer: [new UglifyJsPlugin(), new OptimizeCssAssetsPlugin()]
      
    ;

package.json


  "name": "project_name",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": 
    "build": "webpack --mode=production",
    "dev": "webpack --watch",
    "stage": "npm run clean && webpack --config webpack.stage.js -p --progress --profile",
    "clean": "rm -rf stage"
  ,
  "repository": 
    "type": "git",
    "url": ""
  ,
  "keywords": [
    "webpack"
  ],
  "author": "",
  "license": "ISC",
  "bugs": 
    "url": ""
  ,
  "homepage": "",
  "devDependencies": 
    "@babel/cli": "^7.14.5",
    "@babel/core": "^7.6.2",
    "@babel/preset-env": "^7.6.2",
    "autoprefixer": "^9.6.4",
    "babel-eslint": "^10.0.3",
    "babel-loader": "^8.0.6",
    "browser-sync": "^2.27.4",
    "browser-sync-webpack-plugin": "^2.2.2",
    "css-loader": "^3.2.0",
    "css-mqpacker": "^7.0.0",
    "eslint": "^6.5.1",
    "eslint-config-prettier": "^6.4.0",
    "eslint-config-wordpress": "^2.0.0",
    "eslint-loader": "^3.0.2",
    "eslint-plugin-prettier": "^3.1.1",
    "extract-text-webpack-plugin": "^3.0.2",
    "file-loader": "^4.2.0",
    "img-loader": "^3.0.1",
    "mini-css-extract-plugin": "^0.8.0",
    "node-sass": "^4.14.1",
    "optimize-css-assets-webpack-plugin": "^5.0.3",
    "postcss-loader": "^3.0.0",
    "prettier": "^1.18.2",
    "resolve-url-loader": "^4.0.0",
    "sass-loader": "^8.0.0",
    "style-loader": "^1.0.0",
    "stylelint": "^11.0.0",
    "stylelint-config-recommended-scss": "^4.0.0",
    "stylelint-config-wordpress": "^15.0.0",
    "stylelint-order": "^3.1.1",
    "stylelint-scss": "^3.11.1",
    "stylelint-webpack-plugin": "^1.0.1",
    "svg-sprite-loader": "^4.1.6",
    "svgo": "^1.3.0",
    "svgo-loader": "^2.2.1",
    "uglifyjs-webpack-plugin": "^2.2.0",
    "url-loader": "^4.1.1",
    "webpack": "^4.41.0",
    "webpack-cli": "^3.3.9",
    "wp-pot-cli": "^1.5.0"
  ,
  "dependencies": 
    "@babel/polyfill": "^7.6.0",
    "imagemin": "^8.0.0",
    "jquery": "^3.6.0"
  

【问题讨论】:

【参考方案1】:

我过去也遇到过类似的问题,我从文档中尝试了以下内容,

const ASSET_PATH = process.env.ASSET_PATH || '/';

export default 
  output: 
    publicPath: ASSET_PATH,
  ,

  plugins: [
    // This makes it possible for us to safely use env vars on our code
    new webpack.DefinePlugin(
      'process.env.ASSET_PATH': JSON.stringify(ASSET_PATH),
    ),
  ],
;

但实际上,最适合我的问题的方法如下,而公共路径是提供资产的 CDN 链接

  require('dotenv').config();
  __webpack_public_path__ = config.publicPath // publicPath is process.env.ASSET_PATH || '/';

当您设置publicPath as "../" 时,您是否也尝试了useRelativePaths: true

参考:-https://github.com/webpack-contrib/file-loader#userelativepath

【讨论】:

以上是关于Webpack:如何在 .css 中重写 URL的主要内容,如果未能解决你的问题,请参考以下文章

如何重写 webpack.config.js 并为 LARAVEL 8 添加 SASS

如何强制 CSS url 尊重 webpack 的 publicPath 设置?

如何在 Webpack 中使用 css 中的图像

url重写后如何知道原始url?

Laravel 5 - URL 重写和 CSS 冲突

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