Skip to content
This repository was archived by the owner on May 29, 2019. It is now read-only.

publicPath parameter doesn't work? #246

Closed
yugasun opened this issue Sep 15, 2016 · 16 comments
Closed

publicPath parameter doesn't work? #246

yugasun opened this issue Sep 15, 2016 · 16 comments

Comments

@yugasun
Copy link

yugasun commented Sep 15, 2016

When I use extract-text-webpack-plugin output css file into a folder, the image url is wrong, my webpack config is below:

"use strict";
var path = require('path');
var webpack = require('webpack');

// webpack plugins
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');


module.exports = {
    entry: path.resolve(__dirname, 'app/scripts/main.js'),
    output: {
        path: path.resolve(__dirname, "build"),
        //publicPath: path.resolve(__dirname, "build"),
        filename: 'js/[name]-[hash].js'
    },
    module: {
        loaders: [
            {
                test: /\.jsx?$/,   
                loader: 'babel',    
                exclude: /(node_modules|bower_components)/,
                query: {
                    presets: ['react', 'es2015']
                }
            },
            {
                test: /\.scss$/,
                exclude: /(node_modules|bower_components)/,
                loader: ExtractTextPlugin.extract('style', 'css!sass!postcss')
            },
            {
                test: /\.css$/,
                exclude: /(node_modules|bower_components)/,
                loader: ExtractTextPlugin.extract('style', 'css!postcss')
            },
            {
                test: /\.(woff|woff2|svg|eot|ttf)/,
                loader: 'url?prefix=font/&limit=10000'
            },
            {
                test: /\.(png|jpe?g|gif|svg)$/,
                loaders: [
                    'file?name=images/[name].[ext]',
                    //'image-webpack'
                ]
            }
        ]
    },

    // image handle
    //imageWebpackLoader: {
    //    progressive: true,
    //    optimizationLevel: 3,
    //    interlaced: false,
    //    pngquant: {quality: "65-70", speed: 4}
    //},

    postcss: [
        require('autoprefixer')
    ],

    plugins: [
        new webpack.BannerPlugin('This file is created by yugasun'),
        new HtmlWebpackPlugin({
            title: 'RedChild',
            template: __dirname + '/app/template/index.tmpl.html'
        }),
        new webpack.optimize.OccurenceOrderPlugin(),
        new webpack.optimize.UglifyJsPlugin(),
        new ExtractTextPlugin('css/[name]-[hash].css')
    ]
};

my output 'build' folder tree like this:

.
├── css
│   └── main-72c33a6c0ad73a5a0403.css
├── images
│   ├── arrow.png
|   |.....
│   └── wrong_title.png
├── index.html
└── js
    └── main-72c33a6c0ad73a5a0403.js

But in my output css file the image url is 'images/arrow.png', what I want is like '../images/arrow.png'.

Then I add the extract-text-webpack-plugin options like below:

Change:

new ExtractTextPlugin('css/[name]-[hash].css')

To:

new ExtractTextPlugin('css/[name]-[hash].css', {
            publicPath: '../'
        })

But the parameter 'publicPath' doesn't work, in my output css file the image url is still 'images/arrow.png'.

My package.json is like bellow:

{
  "name": "h5-webpack-template",
  "version": "1.0.0",
  "description": "H5 Develop template.",
  "main": "bundle.js",
  "scripts": {
    "dev": "webpack-dev-server --progress --colors --content-base build --port 8014 --host 0.0.0.0",
    "build": "NODE_ENV=production webpack --config ./webpack.production.js --progress"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/yugasun/H5%2Bwebpack.git"
  },
  "keywords": [
    "webpack",
    "ES6",
    "HTML5"
  ],
  "author": "yugasun",
  "license": "MIT",
  "devDependencies": {
    "autoprefixer": "^6.4.0",
    "babel-core": "^6.13.2",
    "babel-loader": "^6.2.4",
    "babel-preset-es2015": "^6.13.2",
    "babel-preset-react": "^6.11.1",
    "clean-webpack-plugin": "^0.1.10",
    "css-loader": "^0.21.0",
    "extract-text-webpack-plugin": "^1.0.1",
    "file-loader": "^0.8.5",
    "html-webpack-plugin": "^2.22.0",
    "image-webpack-loader": "^2.0.0",
    "imagemin-webpack-plugin": "^1.0.8",
    "node-sass": "^3.4.2",
    "normalize.css": "^4.2.0",
    "postcss-loader": "^0.9.1",
    "sass-loader": "^3.1.2",
    "style-loader": "^0.13.0",
    "url-loader": "^0.5.7",
    "webpack": "^1.13.2",
    "webpack-dev-server": "^1.15.2",
    "webpack-spritesmith": "^0.2.6"
  },
  "bugs": {
    "url": "https://github.com/yugasun/H5%2Bwebpack/issues"
  },
  "homepage": "https://github.com/yugasun/H5%2Bwebpack#readme",
  "dependencies": {
    "weui": "^0.4.3"
  }
}
@heylookltsme
Copy link

I'm running into this same issue.

@toomuchdesign
Copy link

Think you should set the overriding publicPath directly into the extracting loader, like:

loader: ExtractTextPlugin.extract('style',['css'],{publicPath:'./fonts/'})

See: #212

@nblackburn
Copy link

nblackburn commented Oct 16, 2016

Tried numerous configurations, none of which work.

At this point, i am reasonably confident it doesn't do anything.

@adamgotterer
Copy link

I've played with the config and tens of combinations for hours without even a hint of it doing anything. Any work arounds?

@heylookltsme
Copy link

I ended up using a textTransformLoader and fixed the urls myself with a regex. Seems totally unnecessary, but whaddya gonna do. ¯_(ツ)_/¯

@heylookltsme
Copy link

Here's some code in case it's helpful:

textTransformLoader: {
    fixPaths: {
        transformText: function(content) {
            // Internal production builds (gh-pages for internal repo) require a
            // path prefix for all urls.
            if (flags.production && flags.internal) {
                content = content.replace(/(url\(\\?['"])(\/.+?\))/g, '$1/' + config.internalPathPrefix + '$2');
            }

            return content;
        },
    },
},

@githoniel
Copy link

@heylookltsme i have met the same problem, could you expain how you config textTransformLoader?
tried for a long time , but none of which work.

@heylookltsme
Copy link

Ah, sure thing. Yeah, there's a missing puzzle piece here. I'm using it with the ExtractTextPlugin.

So the relevant portions of the config look like this:

        module: {
            loaders: [
                {
                    test: /\.scss$/,
                    loader: ExtractTextPlugin.extract(
                        flags.production ? 'style' : 'style?sourceMap',
                        flags.production ?
                            'text-transform?pack=fixPaths!css!postcss!sass' :
                            'text-transform?pack=fixPaths!css?sourceMap!postcss!sass?sourceMap'
                    ),
                },
            ],
        },
        textTransformLoader: {
            fixPaths: {
                transformText: function(content) {
                    // Internal production builds (gh-pages for internal repo) require a
                    // path prefix for all urls.
                    if (flags.production && flags.internal) {
                        content = content.replace(/(url\(\\?['"])(\/.+?\))/g, '$1/' + config.internalPathPrefix + '$2');
                    }

                    return content;
                },
            },
        },
        plugins: [
            new ExtractTextPlugin('index.css', {
                allChunks: true,
            }),
        ],

Notice the fixPaths reference in the ExtractTextPlugin config for .scss files. That's the delicate, hidden thread tying it all together.

I hope that's helpful! Let me know if you're still having trouble.

@githoniel
Copy link

@heylookltsme thank you very much and it works perfect~~~

@yugasun
Copy link
Author

yugasun commented Dec 14, 2016

@heylookltsme thank you very much, I have solve the problem by redefine publicPath for file-loader, as below config:

module: {
     loaders: [
            {
                test: /\.(png|jpe?g|gif)$/,
                loader: 'file',
                query: {
                    limit: 8192,
                    name: 'img/[name].[ext]',
                    publicPath: '/build/'
                }
            },
      ]
},
...
plugins: [
        ...
        new ExtractTextPlugin('css/[name]-[hash].css'),
        
],
            

PS: Maybe this bug has been fixed by the PR #305

@bebraw bebraw added the question label Jan 9, 2017
@bebraw
Copy link
Contributor

bebraw commented Feb 19, 2017

Can you confirm this against webpack 2?

@yugasun
Copy link
Author

yugasun commented Feb 21, 2017

@bebraw I haven't use webpack 2, the config is for webpack 1.14.

@bebraw
Copy link
Contributor

bebraw commented Feb 21, 2017

Ok. Note that you can set publicPath at extract-text-plugin itself. That will likely fix your issue.

If you can confirm it's broken with webpack 2, please re-open.

@bebraw bebraw closed this as completed Feb 21, 2017
@mohammadalipak
Copy link

mohammadalipak commented Jun 12, 2017

my config that worked looks like this:

    rules: [
      // Extract all .global.css to style.css as is
      {
        test: /\.global\.css$/,
        use: ExtractTextPlugin.extract({
          use: 'css-loader',
          fallback: 'style-loader',
          publicPath: './',
        })
      },
      // Pipe other styles through css modules and append to style.css
      {
        test: /^((?!\.global).)*\.css$/,
        use: ExtractTextPlugin.extract({
          use: {
            loader: 'css-loader',
            options: {
              modules: true,
              importLoaders: 1,
              localIdentName: '[name]__[local]__[hash:base64:5]',
            }
          },
          publicPath: './',
        }),
      },
      // Add SASS support  - compile all .global.scss files and pipe it to style.css
      {
        test: /\.global\.scss$/,
        use: ExtractTextPlugin.extract({
          use: [
            {
              loader: 'css-loader'
            },
            {
              loader: 'sass-loader'
            }
          ],
          fallback: 'style-loader',
          publicPath: './',
        })
      },

@bobrosoft
Copy link

bobrosoft commented Jun 14, 2017

Solved similar problem just by disabling of url(...) processing in css-loader by setting url option to false.

{loader: 'css-loader', options: {url: false}}

Before I had issue during SCSS compilation when writing background: url('assets/... so needed to write background: url('/assets/... which is not working for non-root baseUrl (tried all publicPath stuff I can find). Now I can use relative url('assets/... paths in CSS.

@leebenson
Copy link

I'm having a similar problem to the one that originally started this thread. Here's my folder structure:

├── assets
│   ├── css
│   │   ├── style.css
│   │   └── style.css.map
│   └── fonts
│       └── barbershop.8791f5128e84171e9aa3543f533db26b.ttf

What I'd like to happen is that all calls inside of assets/css/style.css will load paths relative to assets/css. So for example, to load the hashed Barbershop font file, I'd expect to see:

url(../fonts/barbershop.8791f5128e84171e9aa3543f533db26b.ttf);

Instead, by default, I'm seeing:

url(assets/fonts/barbershop.8791f5128e84171e9aa3543f533db26b.ttf);

... which then means the browser is looking for assets/css/assets/fonts/..., which is clearly wrong.

The obvious answer is just to set publicPath: '/', so that it's always pulling from the root. However, I'm using this in a framework where users can mount the app at any point, so I want to keep paths relatively to the CSS file, and not to the web root.

The closest I've been able to get to solving it is setting to publicPath: '../../', which yields:

url(../../assets/fonts/barbershop.8791f5128e84171e9aa3543f533db26b.ttf)

... and works well. But - those unnecessary ../../assets bytes are bugging me, when I should be able to just replace those with ../.

The text-transform-loader seems like the perfect solution to the above, but in Webpack 3 and with the current version of Extract Text Plugin, putting them at the front of my loaders yields a content block that looks like the following (instead of the expected final output):

exports = module.exports = require("../node_modules/css-loader/lib/css-base.js")(true);
// imports

// module
exports.push([module.id, "@font-face{font-family:Barbershop;src:url(" + require("./barbershop.ttf") + ") format("truetype")}html{font-family:Barbershop}", "", {"version":3,"sources":["/Users/leebenson/dev/sandbox/reactql-fonts/styles.global.css"],"names":[],"mappings":"AAAA,WACE,uBAA0B,oDACoB,CAC/C,KAGC,sBAAwB,CACzB","file":"styles.global.css","sourcesContent":["@font-face {\n font-family: "Barbershop";\n src: url("barbershop.ttf") format('truetype');\n}\n\nhtml {\n font-family: Barbershop;\n}\n"],"sourceRoot":""}]);

// exports

Does anyone know of either:

a) A way to have Extract Text Plugin compare the current output path with the url() block, and call a file relatively

or (probably more likely):

b) Get text-transform-plugin working with the latest version of both Extract and Webpack 3, to modify the final output instead of the garble above.

Any pointers would be appreciated. And sorry for digging up a closed/old issue!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants