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

Honor the public path by removing "/" from generated CSS and JS files #1717

Open
mislam opened this Issue Jul 14, 2018 · 8 comments

Comments

Projects
None yet
7 participants
@mislam
Copy link

mislam commented Jul 14, 2018

  • Laravel Mix Version: 2.1.11 (npm list --depth=0)
  • Laravel Version: 5.4
  • Node Version (node -v): v8.11.3
  • NPM Version (npm -v): 6.1.0
  • OS: macOS High Sierra (10.13.5), Homestead 7, Ubuntu 18.04 LTS

Reference:

This issue was also mentioned in Workbox repository:

GoogleChrome/workbox#1534

Description:

Up until v1.7.2, Laravel-Mix was outputting the js/app.js and css/app.css with a forward slash like:

/js/app.js
/css/app.css

When upgraded to v2.1.11, I noticed a double slash in the path:

//js/app.js
//css/app.css

This ends up resulting these two files to be loaded from http://js/app.js and http://css/app.css which results a 404 error.

However, this works fine for anyone running out-of-the box installation of Laravel. But when the application starts growing and you want to integrate a service worker plugin (i.e. Workbox), then the real monster comes to play (see the Steps To Reproduce section below).

This is only because Laravel-Mix isn't honoring the public path in the first place. Regardless of v1.7.2 or v2.1.11, it shouldn't set the path to "/" after compiling the scripts and sass files. It should rather set the paths relative, such as: "js/app.js" and "css/app.css" instead of "/js/app.js" and "/css/app.css".

I noticed the fonts and images aren't using this leading "/" while outputting them in the public directory. Only the js and css files are including it.

To understand what's being generated from the Workbox plugin, take a look at my precache manifest file generated by the workbox plugin (refer to the Steps To Reproduce section below) while using Laravel Mix v1.7.2:

self.__precacheManifest = [
  {
    "revision": "c1deb96084cecef66f0e1f41e7fe1c96",
    "url": "apple-touch-icon.png"
  },
  {
    "revision": "44f2b77fa6a419081a6271801e5fda28",
    "url": "img/svg/magnifier.svg"
  },
  {
    "revision": "01232e8fd32ab1e8997e",
    "url": "/js/vendor.js"
  },
  {
    "revision": "b72a3712fdabc4d2cc6b138e00ae1e96",
    "url": "img/logo-dark.png"
  },
  {
    "revision": "598b07f2fce824854ebe0bba82b2b397",
    "url": "img/logo-light-small.png"
  },
  {
    "revision": "e8c13486745f6a1c3fd3cc7788eaace2",
    "url": "img/logo-light.png"
  },
  {
    "revision": "0d22b57cc0113eaf5fff48fe2339e738",
    "url": "fonts/icomoon.eot"
  },
  {
    "revision": "ac7e3b54ed37c5dc26bfdbd2ff9a2e83",
    "url": "fonts/icomoon.ttf"
  },
  {
    "revision": "a09c96d925ad889a9fe2169fa977300d",
    "url": "fonts/icomoon.woff"
  },
  {
    "revision": "06dbce2d2e8fc4cafa42319937955521",
    "url": "fonts/icomoon.svg"
  },
  {
    "revision": "3590030f106aae5b66d36fcbd03b2bf0",
    "url": "favicon-16x16.png"
  },
  {
    "revision": "c2d8bfb9b66a4bb17a1e71757b5ee13a",
    "url": "favicon-32x32.png"
  },
  {
    "revision": "7ca2abdc7b1ec65f45104eea49e92b63",
    "url": "favicon.ico"
  },
  {
    "revision": "38d143e25f32fb48f698",
    "url": "/js/manifest.js"
  },
  {
    "revision": "7a9765e1523cee9eed8f",
    "url": "/js/app.js"
  },
  {
    "revision": "7a9765e1523cee9eed8f",
    "url": "/css/vendor.css"
  },
  {
    "revision": "7a9765e1523cee9eed8f",
    "url": "/css/app.css"
  }
];

This worked for me until the forward slashes doubled in Laravel Mix v2.1.11 only for js and css files:

[
  ...
  {
    "revision": "7a9765e1523cee9eed8f",
    "url": "//js/app.js"
  },
  {
    "revision": "7a9765e1523cee9eed8f",
    "url": "//css/vendor.css"
  },
  {
    "revision": "7a9765e1523cee9eed8f",
    "url": "//css/app.css"
  }
  ...
]

If Laravel Mix returns the JS and CSS file paths without any leading slash, that will solve this issue. I hope @JeffreyWay will look into this.

Steps To Reproduce:

Install the workbox-webpack-plugin and then update the webpack.mix.js file to use it for generating the service worker file:

const WorkboxPlugin = require('workbox-webpack-plugin')

...
mix.js(...)
   .sass(...)
   .webpackConfig({
       ...
       plugins: [
           ...
           // Generate service worker
           new WorkboxPlugin.GenerateSW({
               swDest: 'service-worker.js',
               clientsClaim: true,
               skipWaiting: true
           })
       ]
   })
@GuntherDebrauwer

This comment has been minimized.

Copy link

GuntherDebrauwer commented Jul 18, 2018

I'm having the same problem in laravel mix 2.1.

This is problematic if you want to insert script tags into a html using html webpack plugin.
Css files don't seem to have that same problem.

I tried laravel mix 2.0 and the issue is not present in that version.

Can someone help?

my webpack.mix.js code:

const mix = require('laravel-mix');
const HtmlWebpackPlugin = require('html-webpack-plugin');

mix.setPublicPath('dist');

mix.webpackConfig({
  plugins: [
    new HtmlWebpackPlugin({
      template: 'public/index.html',
      filename: 'index.html',
    }),
  ],
});

mix.sass('./src/test.scss', '.css/main.css'); // generates '/css.main.css' in stylesheet link in index.html
mix.js('./src/main.js', 'js/main.js') // generates '//js/main.js' in script tags in index.html. why?
  .extract([
    'vue',
    'vue-router',
    'vuex',
  ]);

if (mix.inProduction()) {
  mix.version();
} else {
  mix.sourceMaps();
}

output in terminal: (the js file uri's should not start with a '/')

images/logo.png?250511dbe7e64107809d0e6d980ff135    5.19 kB          [emitted]
                                     /js/main.js     104 kB       0  [emitted]         /js/main
                                   /js/vendor.js    1.08 MB       1  [emitted]  [big]  /js/vendor
                                 /js/manifest.js    3.84 kB       2  [emitted]         /js/manifest
                                    css/main.css   78 bytes    0, 0  [emitted]         /js/main, /js/main
                                      index.html

EDIT:
my remark on terminal output is not correct. version 2.0 als show /js/main.js and that works (it does not use double slashes in plugins as in v2.1)

@philicevic

This comment has been minimized.

Copy link

philicevic commented Oct 17, 2018

Having the same issue with laravel mix 2.1.14.

I am trying to inject my script via the html-webpack-plugin, but i end up with //js/main.js as src, while the path to my css file looks just fine.

I did try to manipulate the webpack config just to see whats going on and found out that the entry file (which should be js/main.js) already has a leading slash, which shouldn't be there. If I manually change that value on runtime I get the right result.

@JeffreyWay It would be nice to know if the leading slash is intentional. At the moment it just causes problems, at least for me..

Steps To Reproduce

I am using a basic mix setup with a self written plugin called 'mix-html-builder' as an additional dependency.

webpack.mix.js

let mix = require('laravel-mix');

require('mix-html-builder');

mix.setPublicPath('out')
   .js('src/js/main.js', 'js')
   .sass('src/scss/main.scss', 'css')
   .buildHtml('src/index.html', 'index.html', 'src/partials');

In out/index.html the injected script tag looks like this:

<script type="text/javascript" src="//js/main.js"></script>

And as I said, the path of my css file looks fine.

@arubacao

This comment has been minimized.

Copy link

arubacao commented Nov 19, 2018

I'm having the exact same problem as @philicevic .
Did you guys find a work-around or how did you solve the problem?

@tyler36

This comment has been minimized.

Copy link

tyler36 commented Nov 20, 2018

As a hacky workaround, I've added the following to my webpack.mix.js

const replace = require( 'replace-in-file' );
const path = require( 'path' );
const publicDir = 'public/html';
...
mix.js( 'resources/js/app.js', 'js' )
 ...
        .then( () => replace.sync( {
            // FIXME:   Workaround for laravel-mix placeing '//*.js' at the begining of JS filesystem
            files: path.normalize( `${publicDir}/precache-manifest.js` ),
            from:  /\/\//gu,
            to:    '/',
        } ) )

Not too proud of the solution but it works. Hopefully now that @JeffreyWay has finished his site updates, he'll have a bit of time to take a look.

@hlorofos

This comment has been minimized.

Copy link

hlorofos commented Dec 28, 2018

is there any way to apply versions from mix-manifest.json to the files referred from html?

@donmbelembe

This comment has been minimized.

Copy link

donmbelembe commented Jan 21, 2019

Any update about this issue ?

@donmbelembe

This comment has been minimized.

Copy link

donmbelembe commented Jan 21, 2019

@tyler36 your workaround doesn't work for me because precache-manifest file name contain a unique hash precache-manifest.79ad89616b48f59453b7ebaa4d7ca623.js

@tyler36

This comment has been minimized.

Copy link

tyler36 commented Jan 21, 2019

@donmbelembe mine doesn't have a hash.
I'm not that familiar with replace-in-file but it might accept a globs for the filename, then you could do something like

...
files: path.normalize( `${publicDir}/precache-manifest.*.js` ),
...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment