Polymer / prpl-server

⚠️Maintenance mode⚠️ An HTTP server for Node designed to serve PRPL apps in production.
Other
425 stars 29 forks source link

`prpl-server` not working out of the box #24

Closed slightlyoff closed 6 years ago

slightlyoff commented 7 years ago

Hey all,

Was having trouble with static resources in a personal project using prpl-server as an NPM module. To re-create the issue, I've tried to boil things down to the simplest possible test case and repro. Here's what I did:

  1. Update Polymer CLI to the latest
  2. Create a dummy project using the polymer-2-starter-kit template via polymer init
  3. Add build config rules to create PRPL support (see below)
  4. polymer build
  5. Attempt to serve with: prpl-server --root ./build/ --config ./build/polymer.json
  6. Browse to the the app at http://127.0.0.1:8080/

What should happen: the root file and sub-resources should all be served correctly

What does happen: only the root file is correctly selected. Subresources all 404

I modified the default polymer.json to include build rules. Here's the whole file:

{
  "entrypoint": "index.html",
  "shell": "src/my-app.html",
  "fragments": [
    "src/my-view1.html",
    "src/my-view2.html",
    "src/my-view3.html",
    "src/my-view404.html"
  ],
  "sources": [
    "src/**/*",
    "images/**/*",
    "bower.json"
  ],
  "extraDependencies": [
    "manifest.json",
    "bower_components/webcomponentsjs/*.js"
  ],
  "lint": {
    "rules": ["polymer-2"]
  },
  "builds": [
    { "name": "modern",
      "preset": "es6-unbundled",
      "browserCapabilities": ["es2015", "push"]
    },
    { "name": "fallback",
      "bundle": true,
      "js":   { "minify": true, "compile": true },
      "css":  { "minify": true },
      "html": { "minify": true }
    }
  ]
}

/cc @justinfagnani @aomarks @graynorton

aomarks commented 7 years ago

Hey Alex, thanks for trying it out! Try adding "basePath": true to both of those build configs. That will update the <base> tag in each build's entrypoint to point to the right build subdirectory.

aomarks commented 7 years ago

Although, trying this out myself now, I see that with "basePath": true, navigation links now have the build prefix on them, which isn't right.

I think there's a bit of a conflict with how <base> wants to be used used here. polymer-2-starter-kit wants to use the base path to let you mount multiple apps on the same host, hence application routes are relative and get the base path prefix. But for differential serving with prpl-server, we are relying on the <base> tag to mount multiple builds of the same app all from the same host root, so application route hrefs should be absolute.

Will need to think about this a bit. I guess the first question is whether we think it's important to preserve the behavior in the starter kit where you can serve multiple apps from different subdirectories on the same host?

graynorton commented 7 years ago

@aomarks, I think I have that part figured out. In a meeting right now, but let's catch up this morning.

slightlyoff commented 7 years ago

Any update?

graynorton commented 7 years ago

@slightlyoff, the tl;dr is that we identified some incremental changes we needed to land in both the tools and the templates to make everything work out of the box. The tools-side changes landed yesterday, I believe (@aomarks can confirm). The template-side changes have open PRs that we still need to finish up and land.

jorgecasar commented 7 years ago

Same error here. After build I'm runing prpl-server --root ./build/ and this is the log:

Loading config from "build/polymer.json".
Serving files from "/Users/jorgecasar/workspace/github/kairosds/kairos-people/build".
Detected push manifest "fallback/push-manifest.json".
Detected push manifest "modern/push-manifest.json".
Registered entrypoint "modern/index.html" with capabilities [es2015,push].
Registered entrypoint "fallback/index.html" with capabilities [].

prpl-server listening
http://127.0.0.1:8080

But when I access to this URL doesn't find any resource inside bower_components/

ERROR GET http://127.0.0.1:8080/bower_components/webcomponentsjs/webcomponents-loader.js 

As server detects what index.html send should do the same with bower_components.

I don't think that change the <base> tag would be a good idea.

Nitrus commented 7 years ago

Try adding a "build" section and a "name" variable to your polymer.json. I am using this:

{  
...
   "lint":{  
      "rules":[  
         "polymer-2"
      ]
   },
   "builds":[  
      {  
         "name":"manage",
         "preset":"default",
         "addServiceWorker":true,
         "basePath":true
      }
   ]
}

I serve with: prpl-server --root ./build/ --config polymer.json --port 80 And access it by: "localhost/manage". Entrypoint is properly detected as: Registered entrypoint "manage/index.html" with capabilities [].

EDIT: This is in response to @jorgecasar

EDIT2: My apologies, I think I misunderstood your initial issue. My build for example has the href altered according to the build name, and I made sure to load bower components with the relative path: "bower_components/webcomponentsjs/webcomponents-loader.js"

aomarks commented 7 years ago

@jorgecasar Check out the documentation on base paths. Also take a look at the shop example app, which follows the base path pattern and works well with prpl-server.

jorgecasar commented 7 years ago

I found the errors and this is the checklist to make it work in yours projects:

Thanks @aomarks and @Nitrus

slightlyoff commented 7 years ago

The PSK 2.0 demo app (which I reported the original issue against) also sets the base path to /: https://github.com/PolymerElements/polymer-starter-kit/blob/2.0-preview/index.html#L25

Nor does it use absolute URLs.

@aomarks: can you please post step-by-step directions for demonstrating that the Shop demo works? Will re-attempt from my end using that template, but want to understand what we might be doing differently.

slightlyoff commented 7 years ago

Here are the exact commands I ran:

> npm i -g polymer
> npm i -g prpl-server
> mkdir shop
> cd shop
> polymer init
? Which starter template would you like to use? shop
> bower install
> polymer build

This output a single build target:

obelisk:shop alex$ cd build
/Users/alex/projects/oneoffs/prpl/shop/build
obelisk:build alex$ ls -lah
total 0
drwxr-xr-x+  3 alex  staff   102B May 26 13:56 ./
drwxr-xr-x+ 17 alex  staff   578B May 26 13:56 ../
drwxr-xr-x+  8 alex  staff   272B May 26 13:56 default/

...which is not exactly helpful in determining if the PRPL pattern is supported.

The default polymer.json on ToT includes multiple build rules but they don't have names. The version selected via polymer init doesn't seem to include even this. The polymer.json I see is:

{
  "entrypoint": "index.html",
  "shell": "src/shop-app.html",
  "fragments": [
    "src/shop-list.html",
    "src/shop-detail.html",
    "src/shop-cart.html",
    "src/shop-checkout.html",
    "src/lazy-resources.html"
  ],
  "sourceGlobs": [
   "src/**/*",
   "data/**/*",
   "images/**/*",
   "bower.json"
  ],
  "includeDependencies": [
    "manifest.json",
    "bower_components/webcomponentsjs/webcomponents-lite.min.js"
  ]
}

I modified it to include multiple build targets like so:

{
  "entrypoint": "index.html",
  "shell": "src/shop-app.html",
  "fragments": [
    "src/shop-list.html",
    "src/shop-detail.html",
    "src/shop-cart.html",
    "src/shop-checkout.html",
    "src/lazy-resources.html"
  ],
  "sourceGlobs": [
   "src/**/*",
   "data/**/*",
   "images/**/*",
   "bower.json"
  ],
  "includeDependencies": [
    "manifest.json",
    "bower_components/webcomponentsjs/webcomponents-lite.min.js"
  ],
  "extraDependencies": [
    "manifest.json",
    "bower_components/webcomponentsjs/*.js"
  ],
  "builds": [
    {
      "preset": "es5-bundled"
    },
    {
      "preset": "es6-unbundled"
    }
  ]
}

This correctly built multiple targets:

obelisk:shop alex$ polymer build
warn: [polymer-project-config]    "sourceGlobs" config option has been renamed to "sources" and will no longer be supported in future versions
warn: [polymer-project-config]    "includeDependencies" config option has been renamed to "extraDependencies" and will no longer be supported in future versions
info:    Clearing build/ directory...
info:    (es6-unbundled) Building...
info:    (es5-bundled) Building...
info:    (es6-unbundled) Build complete!
info:    (es5-bundled) Build complete!
obelisk:shop alex$ cd build/
/Users/alex/projects/oneoffs/prpl/shop/build
obelisk:build alex$ ls
./      ../     es5-bundled/    es6-unbundled/  polymer.json

...which I then tried to serve:

obelisk:shop alex$ prpl-server --root ./build/ --config ./build/polymer.json
Loading config from "./build/polymer.json".
Serving files from "/projects/oneoffs/prpl/shop/build".
Detected push manifest "es5-bundled/push-manifest.json".
Detected push manifest "es6-unbundled/push-manifest.json".
Registered entrypoint "es6-unbundled/index.html" with capabilities [es2015,push].
Registered entrypoint "es5-bundled/index.html" with capabilities [].

prpl-server listening
http://127.0.0.1:8080

Loading this in the browser shows the same errors as before (see attached image):

image

Please advise.

/cc @mattsmcnulty @aomarks @graynorton @justinfagnani

Nitrus commented 7 years ago

You're missing "name" and "baseHref" in your build section. Name is for it to know what to name the build I believe, and "baseHref":true will make it actually do the change after building. You're serving from /build, but your files are in the build subfolder from what I can see. (es5-bundled) Basically you're accessing with just root localhost, while you should with localhost/buildname. Otherwise you will need to serve from the build's folder

slightlyoff commented 7 years ago

My initial polymer.json included a name; I omitted as @aomarks said that the Shop app works with prpl-server. Adding baseHref now and will report back.

Nitrus commented 7 years ago

I also edited my previous comment just a little bit

slightlyoff commented 7 years ago

Thanks for the leads @Nitrus! Now we're getting somewhere. Here's the updated polymer.json:

{
  "entrypoint": "index.html",
  "shell": "src/shop-app.html",
  "fragments": [
    "src/shop-list.html",
    "src/shop-detail.html",
    "src/shop-cart.html",
    "src/shop-checkout.html",
    "src/lazy-resources.html"
  ],
  "sourceGlobs": [
   "src/**/*",
   "data/**/*",
   "images/**/*",
   "bower.json"
  ],
  "extraDependencies": [
    "manifest.json",
    "bower_components/webcomponentsjs/*.js"
  ],
  "builds": [
    {
      "preset": "es5-bundled",
      "basePath": true
    },
    {
      "preset": "es6-unbundled",
      "basePath": true
    }
  ]
}

I also updated index.html (modified from the default installed by polymer init) to:

<!--
@license
Copyright (c) 2016 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <base href="/">
  <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">

  <title>SHOP</title>

  <link rel="shortcut icon" sizes="32x32" href="images/shop-icon-32.png">

  <meta name="theme-color" content="#fff">
  <link rel="manifest" href="manifest.json">

  <link rel="import" href="src/shop-app.html" async>

  <style>

    body {
      margin: 0;
      font-family: 'Roboto', 'Noto', sans-serif;
      font-size: 13px;
      line-height: 1.5;
      min-height: 100vh;
    }

    /* styling for render while resources are loading */
    shop-app[unresolved] {
      display: block;
      min-height: 101vh;
      line-height: 68px;
      text-align: center;
      font-size: 16px;
      font-weight: 600;
      letter-spacing: 0.3em;
      color: #202020;
      padding: 0 16px;
      overflow: visible;
    }

  </style>

</head>
<body>

  <shop-app unresolved>SHOP</shop-app>

  <script>
    window.performance && performance.mark && performance.mark('index.html');

    Polymer = {lazyRegister: true, dom: 'shadow'};

    (function() {
      if ('registerElement' in document
          && 'import' in document.createElement('link')
          && 'content' in document.createElement('template')) {
        // platform is good!
      } else {
        // polyfill the platform!
        var e = document.createElement('script');
        e.src = 'bower_components/webcomponentsjs/webcomponents-lite.min.js';
        document.body.appendChild(e);
      }
    })();
  </script>

</body>
</html>

This largely works when served from the source directory using:

obelisk:shop alex$ polymer build
warn: [polymer-project-config]    "sourceGlobs" config option has been renamed to "sources" and will no longer be supported in future versions
info:    Clearing build/ directory...
info:    (es6-unbundled) Building...
info:    (es5-bundled) Building...
info:    (es6-unbundled) Build complete!
info:    (es5-bundled) Build complete!
obelisk:shop alex$ prpl-server --root ./build/ --config ./build/polymer.json
Loading config from "./build/polymer.json".
Serving files from "/projects/oneoffs/prpl/shop/build".
Detected push manifest "es5-bundled/push-manifest.json".
Detected push manifest "es6-unbundled/push-manifest.json".
Registered entrypoint "es6-unbundled/index.html" with capabilities [es2015,push].
Registered entrypoint "es5-bundled/index.html" with capabilities [].

prpl-server listening
http://127.0.0.1:8080

Some latent absolute URLs need to be weeded out:

image

A few things are now clear:

Suggest leaving this issue open until the polymer init demos work correctly.

Thanks again for the help, all.

aomarks commented 7 years ago

Sorry this was unclear! Shop at master actually already has the changes needed for this to work mostly out of the box, but it turns out polymer init looks for a 1.0.0 tag, so it wasn't being picked up. I'm looking into whether we can tag a 2.0.0 (since master also uses Polymer 2 class syntax) and make that the new default for polymer init.

In the meantime, this should work:

$ git clone git@github.com:Polymer/shop.git
$ cd shop
$ vim polymer.json # add {basePath: true} to the two builds
$ polymer install
$ polymer build
$ cd build
$ prpl-server
aomarks commented 7 years ago

We should have polymer init pulling in the new version of shop by tuesday (long weekend starting). There are also some changes for polymer-starter-kit-2 that will land soon to smooth things over there.

We still do have a rough edge related to basePath. The basePath rewriting option is needed to make differential serving work, but it doesn't play nice when you want to just serve a build directory directly (e.g. with polymer serve build/modern). So I'm not sure yet if we should make basePath the default for shop (which would mean you could drop that vim step in my previous comment).

aomarks commented 7 years ago

Waiting on https://github.com/Polymer/polymer-cli/pull/782 to get the changes to shop I mentioned.

aomarks commented 7 years ago

polymer init shop now works out of the box with prpl-server, except that the build config it comes with doesn't include the basePath option. We can't really add that as a default, since otherwise the build won't work out of the box with a standard file server. I'm thinking we add a --basePath or maybe --differentialServing flag to polymer CLI which turns it on, and when you want to build for prpl-server, you just always add this flag.

jorgecasar commented 7 years ago

Did you think about include the base tag in the build process (polymer build) if it doesn't exist?

If the tag doesn't exist and property basePath is true, then create tag and set with the correct value. If the tag doesn't exist and property basePath is false nothing happens. Other cases already supported.

aomarks commented 7 years ago

To use this pattern, you need to have made all your static resource hrefs relative, and in that case you really need a base tag set to / for your source anyway, so that it works properly during development. So I think if it's not already there, that indicates that your app isn't actually set up to use this pattern, in which case automatically adding a base tag is probably not going to work (or might break it).

aomarks commented 6 years ago

We've added a new autoBasePath: true option to polymer.json (https://github.com/Polymer/polymer-project-config/pull/48) which should make it a little more ergonomic to configure a project for prpl-server. It's still not exactly out of the box, but I think it's as close as we're going to get. Closing this issue.