How to unify the path of picture resources in js and css by webpack packaging

when webpack packages a project, you often have to deal with the path problem of resources, and there are usually several solutions

.
  1. do not set publicPath , and generate page-based relative paths
  2. set publicPath , relative path and absolute path can be set
  3. set ides/public-path/" rel=" nofollow noreferrer "> _ _ webpack_public_path__ , the resource path in js uses this variable, but the resource in css does not use

Project path:

the development environment is based on the / root directory, so no matter how to set the OK, to the test environment and production environment path will not be able to adapt.

Development Environment Page address: http://localhost:8080/index.html
Development Environment Resource path: http://localhost:8080/[js|css|img]
< hr >
Test Environment Page address: http://www.test.com/webapp/aaa/index.html
Test Environment Resource path: http://cdn.test.com/static/aaa/[js|css|img]
< hr >
production environment page address: http://www.prod.com/webapp/aaa/index.html
production environment resource path: http://cdn.prod.com/static/aaa/[js|css|img]
< hr >

question: the test environment and production environment will only be packaged once. How can the img paths in js and css adapt to different environments?

there are several key points to solve this problem first

1, the domain name and path of page and resource are different, you cannot simply use the relative path
2, the relative path in js is for the current page, the relative path in css is for the current css file
3, js can define resource path prefix variables, css cannot use
4, and you can set publicPath separately for resource types.

problem solving ideas

1. The resource path in js is used to introduce external variables.
for example,: var imgPath = window.staticPath; / / window.staticPath is injected into index.html from the background
from
to : src=

The disadvantage of changing

to dynamic src is that webpack cannot package the images under assets under the dist/img path if the dynamic stitching address is not recognized. Of course, a small trick is to set both src.

2, _ _ webpack_public_path__ variable
variable
for example: _ webpack_public_path__ = window.resourcePath; / / window.resourcePath injects
js into index.html src=https://img.codeshelper.com/upload/img/2021/03/29/c3htwqbsfy114181 / assets/xx.png

the drawback of this approach is that img url in css cannot be used

3, publicpath ,

of configuring images rule in webpack
{ 
  name: "img/[name].[ext]",
  publicPath:"../",
  limit: 1024
}

because publicPath has a higher priority than _ _ webpack_public_path__
, the disadvantage is that img src in js also uses this publicpath, while the relative path in js is based on the current page

4. After looking through the file-loader source code, we find that publicpath, can actually be defined as a function,
, so there is a silly way to set publicpath dynamically

.
{ 
  name: "img/[name].[ext]",
  publicPath: function(url){
    if(assetsUtil.useWebpackPath(url)){
      return `__webpack_public_path__ + ${JSON.stringify(url)}`
    }

    return "../"
  },
  limit: 1024
}

the disadvantage is which resources need to maintain absolute paths and which use relative paths

to sum up, there is not a very effective and convenient way to solve this problem at present. Hope that friends who encounter this problem will put forward some suggestions and suggestions.


at present, vue-cli is applied in the project, and some configurations have been modified. The situation in the three environments is similar to yours, and the level of the test / production environment is deeper than yours.
first let's talk about which configurations have been modified
1- build/utils.js cssLoaders generateLoaders method

// Extract CSS when that option is specified
    // (which is the case during production build)
    if (options.extract) {
      return ExtractTextPlugin.extract({
        use: loaders,
        fallback: 'vue-style-loader',
        publicPath: '../../' //iviewfont
      })
    } else {
      return ['vue-style-loader'].concat(loaders)
    }

2- webpack.base.conf.js module rules configuration for picture type

      {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 1024,
          name: utils.assetsPath('img/[folder]/[name].[ext]')
          // [folder]/ 
          // img,
          // hash
        }
      },

3- config/index.js
dev configuration aside, change the port, occasionally modify the default startup lolocalhost for mobile debugging
is mainly build

assetsPublicPath: './',//./

at present, this configuration is working well. You can still refer to the original cli configuration for the changes in the picture. I am changing according to the requirements of the project.
assetsPath as follows

exports.assetsPath = function (_path) {
  const assetsSubDirectory = process.env.NODE_ENV === 'production'
    ? config.build.assetsSubDirectory
    : config.dev.assetsSubDirectory

  return path.posix.join(assetsSubDirectory, _path)
}
Menu