ionic-team / stencil

A toolchain for building scalable, enterprise-ready component systems on top of TypeScript and Web Component standards. Stencil components can be distributed natively to React, Angular, Vue, and traditional web developers from a single, framework-agnostic codebase.
https://stenciljs.com
Other
12.56k stars 787 forks source link

Configuration publicPath Not Retained for Browser Requests #374

Closed alexstaroselsky closed 6 years ago

alexstaroselsky commented 6 years ago

Stencil version:

 @stencil/core@0.1.0

I'm submitting a:

Current behavior:

stencil.config.js has a publicPath property set. When the "base" component .js file is loaded by the browser (Chrome), component asset .js files are being loaded/requested from the equivalent of the build path such as 'https://foobar.com/mycomponent/mycomponent.cibhru87.js', rather than than publicPath base path specified in stencil.config.js.

Expected behavior: With publicPath property in stencil.config.js set to "/foo/bar/components", the request path for a build generated asset such as mycomponent.cibhru87.js, should be 'https://foobar.com/foo/bar/components/mycomponent.cibhru87.js'. This was working as expected in versions 0.0.9-2 and earlier.

Steps to reproduce:

  1. git clone https://github.com/ionic-team/stencil-component-starter.git my-component
  2. cd my-component
  3. npm install
  4. Add publicPath property of stencil.config.js with value of "/foo/bar/components"
  5. npm run build
  6. Load generated base component file and related assets to server or serve locally using something like http-server
  7. Notice the network tab requests.

Related code:

exports.config = {
  namespace: 'mycomponent',
  generateDistribution: true,
  bundles: [
    { components: [ 'my-component' ] }
  ],
  publicPath: "/foo/bar/components"
};

exports.devServer = {
  root: 'www',
  watchGlob: '**/**'
}

Other information:

Thank you for any help or insight you can provide.

marinho commented 6 years ago

I face the same issue, but I would like to blame the "expected behaviour" part a bit.

It's right that documentation points stencil.config.js' publicPath to be used instead, but the problem with such approach is that it defines the public path from the component perspective, while that might differ in the consumer side, depending on how the components are bundled and published.

It would be nice if there was an option to, instead of having these couple of files suffixed with hashes, we could bundle all of them in one single file (i.e. dist/my-component.js).

alexstaroselsky commented 6 years ago

Up to 0.0.9-2 the publichPath property was effectively and consistently setting the base path for base component entry file as well as the related assets bundled/generated from the build command. In the CMS environment I'm currently working in, I simply am unfortunately unable to put the main component file and it's related assets at the base of the document tree, which is where with the update the related assets are being loaded from, rather than config.publicPath + '/' + nameOfComponentDirectory + '/'.

While one single bundled file would be easier, I feel the dynamic loading of the components assets is a great feature to help ensure only the bare minimum of code is loaded by the browser.

Thank you @ionic-team for this amazing library. It has completely transformed our team's ability to output performant, encapsulated, and platform agnostic elements in our application. The development experience is top-notch, it's really easy to introduce other developers to the workflow and get high quality components shipped out fast.

adamdbradley commented 6 years ago

Thanks for the bug report, we'll get the publicPath fixed up again, thanks

adamdbradley commented 6 years ago

How can i recreate this issue? Right now I'm testing it by setting the publicPath to /js and have a valid js directory within www, and my demo app is requesting everything from /js. What does your setup look like? Thanks

alexstaroselsky commented 6 years ago

Thank you for looking into this! While there definitely is a difference in loading of assets between 0.0.9-2 and 0.1.x, I think this issue can be closed as upon further research it was dealing more with the JavaScript asset loading mechanism of the ASP.NET CMS rather than an error with Stencil. We were able to load the mycomponent.js equivalent in an alternate way that allowed the loading to succeed. I'll provide more information below in case it helps as an edge case in any way.

For us the issue was arising from the following bit of code in loader.ts:

x = doc.scripts[doc.scripts.length - 1];
if (x && x.src) {
  y = x.src.split('/').slice(0, -1);
  publicPath = (y.join('/')) + (y.length ? '/' : '') + appNamespace + '/';
}

The CMS loads the initial mycomponent.js in the following fashion:

https://www.foobar.com/CMSPages/GetResource.ashx?scriptfile=%7e%2fCMSScripts%2ffoo%2fbar%2fcomponents%2fmycomponent.js

The code mentioned below was failing to build a base path inline with the publicPath property as it did in 0.0.9-2 and instead was attempting to load from the root such as /mycomponent/cibhru87.js.

Either way this may likely be an issue with our setup rather than Stencil loader.ts itself.

Thanks!

marinho commented 6 years ago

From my side, the issue I had was actually fixed by changing the script loader (I must use some proprietary script loader which has a funny behaviour), so, I can also say this could be closed.

My other point regarding to having publicPath from the component perspective (not the consumer side) was actually a bit off-topic in here, so, I would like to address in another thread (and I must learn about it a bit more before I bring any suggestion).

Thanks!

jgw96 commented 6 years ago

Thanks for the updates @marinho and @alexstaroselsky ! Closing this issue for now.

yuki24 commented 6 years ago

@jgw96 @marinho I was actually also seeing this issue in a Rails app that's set up using my stenciljs gem. You can find the stencil config file right here in case this is helpful. I also need to learn about how things should be wired up. What's the right channel for having a further conversation? Maybe Slack?

yuki24 commented 6 years ago

Actually, this bug is still present. Given that 28b56383997f0f9449de1bd929e2697d90c2a279 affected at least two major frameworks, I don't believe this is neglectable.

The issue appears only when the loader file is bundled into another javascript file that's not located in the same directory as the loader file. If I understand the loader.ts correctly, it generates a path based on the assumption that the loader is loaded from the publicPath. This may not be true if the application has its own bundler (Parcel, Webpack, ASP.NET, Rails Asset Pipeline, etc) since they output generated into their preferred path.

I can workaround this by just adding a separate <script> tag that loads the stencil loader from the publicPath. Obviously, it'd bring the cost of one extra connection and network roundtrip. It is not a big deal, but I'm sort of reluctant about this workaround since my app is as optimized for the first paint as it should be.

@adamdbradley @jgw96 what are your thoughts on this?