Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to deal with relative public path #46

Closed
adcentury opened this Issue Nov 13, 2015 · 22 comments

Comments

Projects
None yet
@adcentury
Copy link

adcentury commented Nov 13, 2015

I set a relative public path in outputs

output: {
  path: path.join(__dirname, 'www/static'),
  filename: '[hash].bundle.js',
  publicPath: './'
}

Then the file structure is like

www
  |-- static
          | -- bundle.js
          | -- some-image.png
          | -- some-other-image.png
          | -- style.css
  |-- index.html

When i require image in css, i works fine.

But when i require image in some js, the url is wrong.

const url = require('path/to/some-image.png');
// the url will be 'some-image.png'
// but this url will be used in index.html (through react)

Any one can help me with it? Thanks.

@silvenon

This comment has been minimized.

Copy link

silvenon commented Nov 29, 2015

Why don't you set it to / instead?

@adcentury

This comment has been minimized.

Copy link
Author

adcentury commented Dec 9, 2015

Because I want to use these files in cordova app, using '/' will fail.

@export-mike

This comment has been minimized.

Copy link

export-mike commented Jan 4, 2016

yeah same issue here @adcentury any progress?

@dancoates

This comment has been minimized.

Copy link

dancoates commented Feb 12, 2016

It isn't a very good solution but you can work around this issue by placing the scripts and css in the www folder with the index.html and setting publicPath : "". That way it doesn't matter if the files are accessed relative to the html or the css.

@adcentury

This comment has been minimized.

Copy link
Author

adcentury commented Feb 14, 2016

@export-mike The only way I found is to put all files (include html, js, css, images) into the www folder as @dancoates said. By the way, HtmlWebpackPlugin may help with generating html files.

@mummybot

This comment has been minimized.

Copy link

mummybot commented Mar 11, 2016

Are you using these in a separate app? If so, have you tried setting up your webpack dev server to proxy the other app, that way you can use '/' as your publicPath base but still forward requests to other app e.g.

var buildPath = '/wp-content/themes/mytheme/build/';

var config = {
  entry: [
    'webpack-dev-server/client?http://localhost:8080/',
    'webpack/hot/only-dev-server',
    path.join(__dirname, 'src/index.js')
  ],
  output: {
    path: path.resolve(__dirname, 'wp-content/themes/tpbc/build'),
    filename: 'index.js',
    publicPath: buildPath
  },
  devtool: 'eval-source-map',
  resolve: { alias: {} },
  devServer: {
    contentBase: buildPath,
    proxy: {
      '*': {
        target: externalServerURL,
        bypass: function(req) {
          // Make sure that non-webpack assets have the correct host header so any vhost works correctly.
          if (req.headers && req.headers.accept) {
            // Detect requests that do not contain the build directory
            if (req.url.indexOf(buildPath) === -1) {
              req.headers.host = externalServerURL.split('/')[2];
            }
          }
        }
      }
    }
  },
@dancoates

This comment has been minimized.

Copy link

dancoates commented Mar 14, 2016

@mummybot at least in my case the other app is a cordova iphone app, so proxying is not an option.

The core of the problem is that CSS loads assets relative to itself, and js loads assets relative to the HTML. So if the CSS isn't in the same place as the HTML then you can't use relative paths.

It would be good to be able to pass a resolving function to the file loader to allow more complex path resolution.

@bigfengyu

This comment has been minimized.

Copy link

bigfengyu commented Jun 15, 2016

I meet the same problem,do someone knows how to deal with it now?

@evilguc

This comment has been minimized.

Copy link

evilguc commented Jun 16, 2016

Hello. I have faced the same problem trying to pack my web app as "native" ios/android application with Cordova. In my specific case it's a React application with react-router. Web version uses HTML5 History API, so basic relative paths for assets are not work correctly on pages other than "/". But if you use Hash History instead of HTML5 History (which is by the way is recommended for cordova applications, you don't see urls anyway) it seems to work fine.

For more information see this thread: ReactTraining/react-router#2161

So if it's your case you can set publicPath in webpack config to empty string (so you'll get relative paths) and use Hash History with your router.

@export-mike

This comment has been minimized.

Copy link

export-mike commented Jun 16, 2016

I have a config that's working with Cordova and code push I can share with
you tomorrow. We're on react, react router

On Thu, 16 Jun 2016, 12:43 Ilya Gutsalyuk, notifications@github.com wrote:

Hello. I have faced the same problem trying to pack my web app as "native"
ios/android application with Cordova. In my specific case it's a React
application with react-router. Web version uses HTML5 History API, so basic
relative paths for assets are not work correctly on pages other than "/".
But if you use Hash History instead of HTML5 History (which is by the way
is recommended for cordova applications, you don't see urls anyway) it
seems to work fine.

For more information see this thread: ReactTraining/react-router#2161
ReactTraining/react-router#2161

So if it's your case you can set publicPath in webpack config to empty
string (so you'll get relative paths) and use Hash History with your router.


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
#46 (comment),
or mute the thread
https://github.com/notifications/unsubscribe/AC2Fn6Nl3PAn87DXcYHg0_8xaMs6iodqks5qMTbOgaJpZM4Gh22j
.

@ianks

This comment has been minimized.

Copy link

ianks commented Jul 1, 2016

@export-mike can you post that config?

@ianfitzpatrick

This comment has been minimized.

Copy link

ianfitzpatrick commented Jul 13, 2016

I'm having the same problem, not using react but vuejs + cordova.

I tried to setting:

assetsPublicPath: '/',

However the resulting cordova index.html file still ends up with entries like:

<script type=text/javascript src=/static/js/app.2a047fb94d3c535a8f2e.js>

My hacky fix is to just write a little shell script (there is probably a proper webpack post-hook way of doing this but I dunno what it is) to replace all instances of /static/ with static/ and that fixed the problem for me. But not exactly elegant.

I crave a better solution, emailed @export-mike to see if he can share his config with us.

Edit:

Welp actually I'm a dork. The webpack template I'm using has separate sections for assetsPublicPath on dev vs. production, and I was only setting it for dev.

When I set it for production like:

assetsPublicPath: '',

I got this kind of output in cordova's index.html file:

<script type=text/javascript src=static/js/app.2a047fb94d3c535a8f2e.js>

Which works fine in Cordova and when I tested in iOS simulator.

@christianmalek

This comment has been minimized.

Copy link

christianmalek commented Sep 29, 2016

Is there a solution for this now?

@coreyching

This comment has been minimized.

Copy link

coreyching commented Oct 4, 2016

^ bump. The issue I'm having is using vue.js with webpack.

I bind a html tag like this: <img v-bind:src="resource.img"> to dynamically load an image.

when the client renders the page, the src path is correct, however it is the actual relative path (e.g. "../assets/example.png" etc, instead of the path webpack outputs. Thus, the image creates a 404 because there is no image at "../assets/example.png".

Alternatively, if i hardcode the src <img src="../assets/example.png"> the image loads, and the the src is some path that webpack created, finding the correct image.

@jpmelnik

This comment has been minimized.

Copy link

jpmelnik commented Nov 6, 2016

@yES, @dancoates

The core of the problem is that CSS loads assets relative to itself, and js loads assets relative to the HTML. So if the CSS isn't in the same place as the HTML then you can't use relative paths.

{
        test: /\.png$/,
        loader: "file-loader?name=images/[name].[ext]"
      },

I fix it partially with "url-loader", It generate data:image/png;base64

{
        test: /\.png$/,
        loader: "url-loader?name=images/[name].[ext]"
      },

I replace file-loader with url-loader.

My Webpack.config.js dev mode

const path        = require('path');
const webpack     = require('webpack');
const ExtractText = require('extract-text-webpack-plugin');

module.exports = {
  devServer: { inline: false },
  entry: path.join(__dirname, '/src/assets/javascripts/main.js'),
  output: {
    //path: './dist/assets/',
    //filename: './javascripts/[name].js',
    //publicPath: '../',

    path: './dist/',
    publicPath: '/assets/',
    filename: './javascripts/[name].js'

    // path: './dist/assets/',
    // publicPath: '/assets/',
    // filename: './javascripts/[name].js'
  },
  plugins: [
    new webpack.optimize.UglifyJsPlugin({
      compressor: {
        warnings: false
      },
      output: {
        comments: false
      }
    }),
    new webpack.optimize.OccurrenceOrderPlugin(),
    new ExtractText('./stylesheets/main.css', {
      allChunks: true
    })
  ],
  module: {
    loaders: [
      {
        test : /\.js$/,
        include : path.join(__dirname, '/src/assets/javascripts/'),
        exclude: /node_modules/,
        loader: 'babel-loader',
        query: {
          presets: ['es2015']
        }
      },
      {
        test: /\.css$/,
        loaders: ['style', 'css']
        //loader: "style-loader!css-loader"
      },
      {
        test: /\.scss$/,
        loaders: ['style', 'css?sourceMap', 'sass?sourceMap', ExtractText.extract('css!sass')]
      },
      {
        test: /\.(woff|woff2|ttf|eot|svg)(\?[\s\S]+)?$/,
        loader: 'url-loader?limit=10000&name=fonts/[name].[ext]'
      },
      {
        test: /\.png$/,
        loader: "url-loader?name=images/[name].[ext]"
        //loader: "file-loader?name=images/[name].[ext]"
      },
    ]
  }
};

Other alternative with sass/scss using extract-text-webpack-plugin

{
     test: /\.scss$/,
     loaders: ['style', 'css', 'resolve-url', 'sass?sourceMap', ExtractText.extract(['css', 'sass'], {
          publicPath: '../'
     })]
 },
@azz0r

This comment has been minimized.

Copy link

azz0r commented Nov 26, 2016

I believe I'm also suffering from the same issue and the above gives me:

fs.js:640
  return binding.open(pathModule._makeLong(path), stringToFlags(flags), mode);
                 ^

Error: ENOENT: no such file or directory, open '/Users/azz0r/Sites/Personal/wwe-draft-generator/build/static/app.bundle.js'
    at Error (native)
    at Object.fs.openSync (fs.js:640:18)
    at Object.fs.readFileSync (fs.js:508:33)
    at /Users/azz0r/Sites/Personal/wwe-draft-generator/scripts/build.js:31:29
@prewk

This comment has been minimized.

Copy link

prewk commented Dec 1, 2016

I'm using publicPath: '' which allows you to set it at runtime with __webpack_public_path__ (as per https://webpack.github.io/docs/configuration.html)

My CSS and JS is loading correctly from the CDN environment I upload them to and point towards with __webpack_public_path__.

If I, however, use file-loader to load a PNG file in a React component, the resulting path will be calculated from some other algorithm, causing the PNG image to be loaded locally from the web server instead of the CDN.

Is file-loader supposed to adhere to __webpack_public_path__?

@bjornstar

This comment has been minimized.

Copy link

bjornstar commented Dec 13, 2016

@prewk I ran into the same problem, webpack/webpack#971 had the clue that got it working for me.

Add a new entry before your other ones and modify __webpack_public_path__ there.

@prewk

This comment has been minimized.

Copy link

prewk commented Dec 13, 2016

Thanks, that's exactly how I'm setting it at the moment, though. I ended up not using the file-loader for my problem and going for data-uris instead.

@asuishi

This comment has been minimized.

Copy link

asuishi commented Mar 16, 2017

Is there a solution for this now? v1 or v2
require image in css and js

@d3viant0ne

This comment has been minimized.

Copy link
Member

d3viant0ne commented Mar 31, 2017

closed in #135 and available in v0.11.0

@danderson00

This comment has been minimized.

Copy link

danderson00 commented Sep 18, 2018

For those reading who are using create-react-app and don't want to eject, this is possible to work around by setting "homepage": "./" in package.json.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.