GithubHelp home page GithubHelp logo

jaredpalmer / after.js Goto Github PK

View Code? Open in Web Editor NEW
4.1K 49.0 201.0 4.59 MB

Next.js-like framework for server-rendered React apps built with React Router

Home Page: https://npm.im/@jaredpalmer/after

License: MIT License

JavaScript 39.44% TypeScript 58.77% CSS 1.70% Shell 0.09%
react server-side-rendering ssr webpack react-router razzle

after.js's Issues

[Help Wanted]: Prefetching / caching

Right now we pass down prefetch: (pathname: string) => void as a prop to each page. It keeps a cache of the result in _app.js's this.prefetcherCache. There is probably a nicer way and more performant way to keep this data around. Please chime in here.

Regarding cache invalidation, wondering if we should have a second argument that is either:

  • number of milliseconds to keep the result
  • a function used to determine whether or not to use the cached data
  • something else

Thoughts?

Nested Routing

How could the behavior in _routes.js be done in smaller sections of the application? I like the idea of a single top level router mechanism, but how would you implement routing inside one of the pages (like '/about', '/about/foo', '/about/bar') without duplicating the code and adding them as top level routes?

PS: I was curios to test this out with a Layout component so I can do an example PR maybe it makes more sense to talk about that one.
PS2: Awesome work, I love this idea

Improve contributor tooling

Lots of restarts are required, need to add a watch command and make gulp tasks more forgiving to syntax errors.

Database connection

It would be a problem if I make database connection instead of using CallMyAPI pattern ?

Discussion: Render Blocking Flag

Although I prefer to set state.data to undefined during page changes (which allows for an easy way to writing a loading indicator), some users may want to keep existing state present. We could potentially accomplish this with a flag.

Thoughts?

introducing env-hoc lib / feature request

Made a library for easier working with cookies / supported languages / userAgent / ipAddress in Next.js (works also with After.js). Check it out: env-hoc.

While I was writing the library I thought about the idea of having a specification for getInitialProps, would make it easier to write libraries and ensure that in the near future there won't be a dozen of frameworks with there own getInitialProps implementation. The most important thing would be to ensure the arguments passed to getInitialProps are the same and that they support Promises / async. What's your opinion? And what do you think about implementing an additional prop to the getInitialProps object named serverProps, which gives access to the result of server-rendered getInitialProps instead of accessing the props somewhat hacky through window.__NEXT_DATA__.props. For libraries, there isn't really any other solution and the props are so-or-so available.

Would also like to hear your opinion. vercel/next.js#3625

fs.copyfile is not a function

node_modules/@jaredpalmer/after/scripts/start.js:100
      fs.copyFile(changedPath, tempSrc.replace('src', changedPath), err => {
         ^

TypeError: fs.copyFile is not a function
    at FSWatcher.chokidar.watch.on.changedPath (/home/paul/web/-cart/node_modules/@jaredpalmer/after/scripts/start.js:100:10)
    at emitTwo (events.js:125:13)
    at FSWatcher.emit (events.js:213:7)
    at FSWatcher.<anonymous> (/home/paul/web/-cart/node_modules/chokidar/index.js:198:15)
    at FSWatcher._emit (/home/paul/web/-cart/node_modules/chokidar/index.js:240:5)
    at FSWatcher.<anonymous> (/home/paul/web/-cart/node_modules/chokidar/lib/nodefs-handler.js:263:16)
    at FSReqWrap.oncomplete (fs.js:153:5)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] start: `after start`

I get this error after following the guide and saving a change in either Home or About.

also tried erasing everything and starting from scratch.

node v8.4.0
npm v5.6

Overriding or extending server config

Is there a way to create your own server config (Changing ports, using custom routes, enable specific middleware, etc.) ? I searched but couldnt find anything in the documentation or issues.

Overridable Document

Allow users to override a custom _document.js that would be rendered to string on the server.

Psuedo code...

import React from 'react';
import Helmet from 'react-helmet' 

class Document extends React.Component {
   static getInitialProps() {
    // call this before calling ReactDOMServer.renderToString   
    return { stuff: 'like css' }
   }
   
    render() {
      const { stuff } = this.props
      return (
       <html>
         <head>
             
         </head>
         <body>
           
         </body>
       </html>
       );
   }

}

export default Document;

take the routes file as a param instead of hardcoded?

Just wondering... it seems like from reading the docs that After always takes a src/_routes.js file as input, and doesn't care about the rest of the directory structure other than that? If so, it seems like it would be awesome if it actually took that file's path as an input similar to other bundlers, instead of enforcing any directory structure at all, like:

after ./src/_routes.js

Or, up to the user at the point...

after ./src/routes.js
after ./browser/index.js
after ./routes.js
...

I might have missed other reasons that After enforces a specific directory structure though in my quick reading, so feel free to close if so.

Layout pages

Nice work, this looks really promising.

I have a small question, is there a way to define a layout, to reuse a component on each page (e.g., a navigation component) ?

Got error on installing package

Hi @jaredpalmer ,

I love this library so much by reading the philosophy / project goals, I was wondering, it would be amazing if next.js had react-router v4 as its routing system rather than dealing with project structure. now this is really happening.

I got a little problem on installing this package.
I use this script as in readme

npm i @jaredpalmer/after react-router-dom react-dom --save

then I got this error

npm ERR! Windows_NT 10.0.10586
npm ERR! argv "C:\Program Files\nodejs\node.exe" "C:\Program Files\nodejs\node_modules\npm\bin\npm-cli.js" "i" "@jaredpalmer/after" "react-router-dom" "react-dom" "--save"
npm ERR! node v7.6.0
npm ERR! npm v4.1.2
npm ERR! code E404
npm ERR! 404 Not found : jaredpalmer/after
npm ERR! 404
npm ERR! 404 jaredpalmer/after is not in the npm registry.
npm ERR! 404 You should bug the author to publish it (or use the name yourself!)
npm ERR! 404
npm ERR! 404 Note that you can also install from a
npm ERR! 404 tarball, folder, http url, or git url.
npm ERR! Please include the following file with any support request:
npm ERR! D:\EXPERIMENT\REACT\after-app\npm-debug.log

Could you please help me?

Thank you

Module not found: Can't resolve 'react-dom/unstable-native-dependencies'

Hi ! I tried to use react-native-web in after.js but I've got this error :

Module not found: Can't resolve 'react-dom/unstable-native-dependencies'

The error is located in a file from react-native-web but It doesn't seem to be directly link to this project.

I deleted .babelrc from my after.js project, delete all imports of react-native-web. Then adding in a component :

import ReactDOMUnstableNativeDependencies from 'react-dom/unstable-native-dependencies'

And it produce the same error.

I also tried in a next.js project and it doesn't produce this error.

node v9.1.0
yarn 1.3.2
react & react-dom 16.2.0
after 0.5.1

On code change recompiling error

Hi, I get this error after any code edit. I've started with basic "hello world" app:

  • Start with blank project, add dependencies
  • Add single route, single component.
  • Start server, compiling is fine
  • Edit any file, recompiling fails

Mac OS - 10.13.1, node version - 8.2.1

`Your application is running at http://localhost:3000

Started server on port 3000
/Users/zigi/Temp/after.js/node_modules/@jaredpalmer/after/scripts/start.js:100
fs.copyFile(changedPath, tempSrc.replace('src', changedPath), err => {
^

TypeError: fs.copyFile is not a function
at FSWatcher.chokidar.watch.on.changedPath (/Users/zigi/Temp/after.js/node_modules/@jaredpalmer/after/scripts/start.js:100:10)
at emitOne (events.js:115:13)
at FSWatcher.emit (events.js:210:7)
at FSWatcher. (/Users/zigi/Temp/after.js/node_modules/chokidar/index.js:198:15)
at FSWatcher._emit (/Users/zigi/Temp/after.js/node_modules/chokidar/index.js:240:5)
at FSWatcher. (/Users/zigi/Temp/after.js/node_modules/chokidar/lib/fsevents-handler.js:206:14)
at addOrChange (/Users/zigi/Temp/after.js/node_modules/chokidar/lib/fsevents-handler.js:212:7)
at FSWatcher. (/Users/zigi/Temp/after.js/node_modules/chokidar/lib/fsevents-handler.js:238:16)
at filteredListener (/Users/zigi/Temp/after.js/node_modules/chokidar/lib/fsevents-handler.js:60:7)
at /Users/zigi/Temp/after.js/node_modules/chokidar/lib/fsevents-handler.js:85:11
at Array.forEach (native)
at FSEvents. (/Users/zigi/Temp/after.js/node_modules/chokidar/lib/fsevents-handler.js:84:34)
at emitThree (events.js:135:13)
at FSEvents.emit (events.js:216:7)
at Immediate._onImmediate (/Users/zigi/Temp/after.js/node_modules/fsevents/fsevents.js:47:11)
at runCallback (timers.js:781:20)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] start: after start
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] start script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR! /Users/zigi/.npm/_logs/2018-01-22T09_44_57_431Z-debug.log`

package.json:
{ "name": "after", "version": "1.0.0", "description": "", "scripts": { "start": "after start", "test": "after test --env=jsdom", "build": "after build", "start:prod": "NODE_ENV=production node build/build/server.js" }, "author": "", "license": "ISC", "dependencies": { "@jaredpalmer/after": "^0.5.2", "react": "^16.2.0", "react-dom": "^16.2.0", "react-helmet": "^5.2.0", "react-router-dom": "^4.2.2" } }

Component rendering twice, once without initialProps

You can replicate with the GraphQL example by loading / and navigating to /posts on the client.

Order of occurrences:
Initial props are fetched
static getInitialProps() on WithData is called
render WithData (without props)
ERROR required prop missing
render WithData (with props)

This leads me to believe it's an issue with _app.js and/or routing

How push to cloud (using now.sh)

I struggled a lot to make this work, but I get issues regarding 'build' script.

Using only the example:

> ...
> Using Node.js 8.9.4 (requested: `8.x.x`)
> Ready! ... [10s]
> Synced 13 files (286.97KB) [0ms]
> Initializing…
> Building
> ▲ npm install
> ✓ Using "package-lock.json"
> ⧗ Installing 5 main dependencies…
> ✓ Installed 1465 modules [56s]
> ▲ npm run build
> > [email protected] build /home/nowuser/src
> > after build
> Failed to compile.
> ENOENT: no such file or directory, stat '/home/nowuser/src/public'
> npm ERR! code ELIFECYCLE
> npm ERR! errno 1
> npm ERR! [email protected] build: `after build`
> npm ERR! Exit status 1
> npm ERR!
> npm ERR! Failed at the [email protected] build script.
> npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
> npm ERR! A complete log of this run can be found in:
> npm ERR!     /home/nowuser/.npm/_logs/2018-01-17T03_42_56_496Z-debug.log
> Error! The build step of your project failed. To retry, run `now --force`.

I've tried adding and excluding folder '/build' in .gitignore but the results are very different with each deploy. Any advice?

Sass webpack extension breaks typescript example

Beginner here and I'm trying to integrate sass-loader into the with-typescript example. Unfortunately, it seems to break the project. Appending the following:

// after.config.js

...
// Locate css loader and remove it
config.module.rules.filter(rule => !(rule.test && String(rule.test) === String(/\.css$/)));

// Declare scss loader configuration
config.module.rules.push({
    test: /\.(sass|scss)$/,
    use: ['style-loader', 'css-loader', 'sass-loader']
});
...

results in:

 DONE  Compiled successfully

Your application is running at http://localhost:3000

<project-path>/with-typescript/build/build/server.js:1473
	return window && document && document.all && !window.atob;
	^

ReferenceError: window is not defined
    at <project-path>/with-typescript/build/build/server.js:1473:2
    at <project-path>/with-typescript/build/build/server.js:1462:46
    at __dirname../node_modules/style-loader/lib/addStyles.js.module.exports (<project-path>/with-typescript/build/build/server.js:1507:46)
    at Object../build/src/scss/bootstrap.scss (<project-path>/with-typescript/build/build/server.js:1189:81)
    at __webpack_require__ (<project-path>/with-typescript/build/build/server.js:630:30)
    at fn (<project-path>/with-typescript/build/build/server.js:48:20)
    at Object../build/src/Home.tsx (<project-path>/with-typescript/build/build/server.js:744:79)
    at __webpack_require__ (<project-path>/with-typescript/build/build/server.js:630:30)
    at fn (<project-path>/with-typescript/build/build/server.js:48:20)
    at Object../build/src/_routes.tsx (<project-path>/with-typescript/build/build/server.js:1080:64)

Unfortunately, I couldn't find any examples for after.js directly and the ones for razzle didn't help - they have the approach of only including the sass loader on target === "web" and ignoring for the node target. Then the setup compiles properly, however the dev and production build appear to load the scss multiple times. My scss file only contains body { background-color: purple; }. On page load, the background is purple, changes back to white, then back to purple again. Best described as flickering.

I feel like I'm missing something fundamental here and would appreciate if someone could shed some light into this. Thanks in advance!

Client-side subrouting with top level component (Navigation for example).

I've tried creating client-side subroutes like in a fully client-side rendered application with RR4 but After.js seems to be ignorant about any components not defined in _routes.js since only telling React about the components causes After to not even download them and those route pages just display blank. It seems that server-side pre-rendered routing triggers a complete wipe of the root content. My goal with this is to have control over page transition animations and not lose client-side state. If there's a simple solution to having control over partially updating the page based on client-side routes(simplest use case would be for navigation). Another question that falls into this category is: can I have my NavLinks defined in only one component that simply doesn't get wiped on route-change?

I'd be really happy if someone could point me in the direction that I'm failing to see. (basically looking for easy alternative to Next.js regarding this problem)

Overridable built-in components

After.js should allow users to define their own versions of the built-in files:

  • _client.js - Client side mount
  • _document.js - HTML static document container
  • _app.js??? - Route iteration (maybe)

Airbnb eslint error

Right now I can't use airbnb eslint style because it's conflicting with the built-in eslint version, can we have an option to remove eslint entirely and install our own eslint version?

"Expected server HTML to contain..." warning in console

I appreciate this probably isn't an issue with after.js but I can't find a definitive way to resolve it: every once in a while, I get this kind of error in console -

Warning: Expected server HTML to contain a matching text node for "Viewport height: " in <p>.

Once I restart after, it'll work correctly, but then eventually appear again. Where am I going wrong here?

Static Export

This should be fairly straight forward and quite pleasant actually. This will be like Gatsby, but minus the GraphQL.

Objection.js models don't work

I have a project on Razzle with existing working code.

I created a new project, following the Readme. Once I got data fetching working, I started to copy over my old project files.
There were a few gotchas along the way, but got those worked out as well.

Then i began testing the APIs once I stopped getting server compiling errors.

All my knex related calls went through. The ones with Object.js Models
all result in

err TypeError: CoinModel.query is not a function
    at Coins._callee$ (/home/web/build/build/server.js:2082:34)
    at tryCatch (/home/web/node_modules/regenerator-runtime/runtime.js:62:40)
    at Generator.invoke [as _invoke] (/home/web/node_modules/regenerator-runtime/runtime.js:296:22)
    at Generator.prototype.(anonymous function) [as next] (/home/web/node_modules/regenerator-runtime/runtime.js:114:21)
    at step (/home/web/node_modules/babel-runtime/helpers/asyncToGenerator.js:17:30)
    at /home/web/node_modules/babel-runtime/helpers/asyncToGenerator.js:35:14
    at new Promise (<anonymous>)
    at new F (/home/web/node_modules/core-js/library/modules/_export.js:35:28)
    at Coins.<anonymous> (/home/web/node_modules/babel-runtime/helpers/asyncToGenerator.js:14:12)
    at Coins.test (/home/web/build/build/server.js:2097:21)
    at /home/web/build/build/server.js:3815:17
    at Layer.handle [as handle_request] (/home/web/node_modules/express/lib/router/layer.js:95:5)
    at next (/home/web/node_modules/express/lib/router/route.js:137:13)
    at Route.dispatch (/home/web/node_modules/express/lib/router/route.js:112:3)
    at Layer.handle [as handle_request] (/home/web/node_modules/express/lib/router/layer.js:95:5)
    at /home/web/node_modules/express/lib/router/index.js:281:22

I'm going to try swapping out for Bookshelf and seeing if that fixes the problem, but Like I said, it was working code on razzle.

Router Plugins

We could push plugins in a few ways:

  • Gatsby-style: have users specify plugins in after.config.js. What's nice is that these could be webpack OR router plugins.
  • Move _routes.js to use react-router-config and allow the user to specify their own Root component.
  • Something else

Basically, we need to give use the ability to have code execute in a few places:

  • before / after navigation (in _app.js's componentWillReceiveProps or equivalent)
  • before render on the server

@mjackson Would love your input on this.

Create a contributing guide

Hello! first, congratulations for that amazing project !

I'm thinking that's a good way to help new contributors to understand the architecture and patterns of the project, before start code something...

What do you think about it? and how I could help you with that ?

Thanks!

getInitialProps not fetching on page refresh

Great project! 👍

Some questions:
Seems like static async getInitialProps only gets called when using a Link to access the route.

For example If you refresh on the /about route, you will see the page gets stuck on "Loading..." and nothing is ssr'd when you view source:
https://after-examples-basic-wycoflvnsg.now.sh/

Am I misunderstanding the framework? Should data returned from getInitialProps get server side rendered? The docs lead me to believe yes, but this isnt working as expected:

import React from 'react';
import { NavLink } from 'react-router-dom';

class About extends React.Component {
  static async getInitialProps({ req, res, match }) {
    const hn = await fetch('https://node-hnapi.herokuapp.com/news');
    const stuff = await hn.json();
    return { stuff };
  }

  render() {
    return (
      <div>
        <NavLink to="/">Home</NavLink>
        <NavLink to="/about">About</NavLink>
        <h1>About</h1>
        <pre>
          {this.props.stuff
            ? this.props.stuff.map(item => <p key={item.id}>{item.title}</p>)
            : 'Loading...'}
        </pre>
      </div>
    );
  }
}

export default About;

Any info appreciated, thanks! And keep up the good work 👍

npm start/build crashes

My package.json (using npm init)


{
  "name": "clinical-web-after",
  "version": "1.0.0",
  "description": "",
  "scripts": {
    "start": "after start",
    "test": "after test --env=jsdom",
    "build": "after build",
    "start:prod": "NODE_ENV=production node build/build/server.js"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@jaredpalmer/after": "^0.5.0",
    "react": "^16.2.0",
    "react-dom": "^16.2.0",
    "react-helmet": "^5.2.0",
    "react-router-dom": "^4.2.2"
  }
}

And the error when running npm start

FMGordillo-MacBookPro:clinical-web-after facundogordillo$ npm start

> [email protected] start /Users/facundogordillo/Documents/Projects/clinical-web-after
> after start

/Users/facundogordillo/Documents/Projects/clinical-web-after/node_modules/@jaredpalmer/after/scripts/start.js:65
async function start() {
      ^^^^^^^^
SyntaxError: Unexpected token function
    at createScript (vm.js:56:10)
    at Object.runInThisContext (vm.js:97:10)
    at Module._compile (module.js:542:28)
    at Object.Module._extensions..js (module.js:579:10)
    at Module.load (module.js:487:32)
    ...

It also happens with npm run build


FMGordillo-MacBookPro:clinical-web-after facundogordillo$ npm run build

> [email protected] build /Users/facundogordillo/Documents/Projects/clinical-web-after
> after build

/Users/facundogordillo/Documents/Projects/clinical-web-after/node_modules/@jaredpalmer/after/scripts/build.js:73
async function build(previousFileSizes) {
      ^^^^^^^^
SyntaxError: Unexpected token function
    at createScript (vm.js:56:10)
    at Object.runInThisContext (vm.js:97:10)
    at Module._compile (module.js:542:28)
    at Object.Module._extensions..js (module.js:579:10)
    at Module.load (module.js:487:32)
    ...

Most probably my mistake, but I want to double check

Custom Express.js server

Hello,
How can we add a custom Express.js server like in Next.js ?

const app = nextjs({dev})
app
.prepare()
.then(() => {
const server = express()
...

AirBnB linting example fails to build

Hi,

I've copied over the .eslintrc and all dependencies from the example into my project and I get an error as soon as I restart:

Using .eslintrc defined in your app root
Using .eslintrc defined in your app root
 ERROR  Failed to compile SERVER with 7 errors

./build/src/index.js
  Line 9:  Expected parentheses around arrow function argument having a body with curly braces  arrow-parens

Search for the keywords to learn more about each error.

 ERROR  Failed to compile SERVER with 7 errors

./build/src/server.js
  Line 5:   Absolute imports should come before relative imports                       import/first
  Line 6:   Absolute imports should come before relative imports                       import/first
....

I won't include the full error as it does it for a number of components.

The .eslintrc I'm using is the same as in the example:

{
  "parser": "babel-eslint",
  "extends": "airbnb",
  "env": {
    "es6": true,
    "browser": true,
    "jest": true,
    "node": true
  },
  "rules": {
    "react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }]
  }
}

As soon as I delete the file all works as standard.

Deps

deps:
"@jaredpalmer/after": "^0.5.2",

devDeps:
"eslint": "^4.16.0",
 "eslint-config-airbnb": "^16.1.0",
    "eslint-plugin-import": "^2.8.0",
    "eslint-plugin-jsx-a11y": "^6.0.3",
    "eslint-plugin-react": "^7.5.1",

Question: How to extend config and add post-css plugins?

How would I go about extending the config and adding a few simple postcss plugins? I've got it working by modifying createConfig.js directly like so:

{
  loader: require.resolve('postcss-loader'),
  options: {
    ident: 'postcss', // https://webpack.js.org/guides/migrating/#complex-options
    plugins: () => [
      require('postcss-easy-import'),
      require('postcss-flexbugs-fixes'),
      require('precss'),
      autoprefixer({
        browsers: [
          '>1%',
          'last 4 versions',
          'Firefox ESR',
          'not ie < 9', // React doesn't support IE8 anyway
        ],
        flexbox: 'no-2009',
      }),
    ],
  },
}

Is there a simple way of doing this in after.config.js?

Should we be transpiling lib?

Everything is copied into from lib to ./build/src so it can theoretically be overridden in user land. However, I'm pretty sure that publishing any untranspiled code to npm is generally considered a bad idea. On the other hand, we can 100% guarantee that this is going to be transpiled. So idk. Thoughts?

cc @gaearon

Integration with the redux

It is desirable to have "out of the box" integration with the redux. So far I can get it all from the next.js and can not with the after.js:
"next-redux-wrapper": redux integration.
"next-routes": after.js's-like routes.

So. I tried to change ./src/_document.js, but it was replaced with system default ./src/_document.js on server start.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.