Git Product home page Git Product logo

Comments (28)

timdeschryver avatar timdeschryver commented on August 24, 2024 2

I had the same issue, I thought the problem was the port 1864 but after some debugging this is what I encountered.

It seems like npm run scully (sometimes?) is giving the following error, and because of this some spawned processes are not being shut down correctly and will stay alive.

C:\Users\tdeschryver\dev\throw-aways\bloggy\node_modules\.bin\scully:2
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
          ^^^^^^^

SyntaxError: missing ) after argument list
    at Module._compile (internal/modules/cjs/loader.js:872:18)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:947:10)
    at Module.load (internal/modules/cjs/loader.js:790:32)
    at Function.Module._load (internal/modules/cjs/loader.js:703:12)

lala at Function.Module.runMain (internal/modules/cjs/loader.js:999:10)
    at internal/main/run_main_module.js:17:11

The next time I run scully the express servers are not spawned because the port is already in use. I would have expected this error to be caught by https://github.com/scullyio/scully/blob/master/scully/utils/staticServer.ts#L64, but this is not the case. By listening to errors, the error showed me that the port was already in use.

 ☺   new Angular build imported
Error: listen EADDRINUSE: address already in use 
    at Server.setupListenHandle [as _listen2] (net.js:1228:14)
    at listenInCluster (net.js:1276:12)
    at Server.listen (net.js:1364:7)
    at Function.listen (C:\Users\tdeschryver\dev\throw-aways\bloggy\node_modules\express\lib\application.js:618:24)         at Object.staticServer (C:\Users\tdeschryver\dev\throw-aways\bloggy\node_modules\@scullyio\scully\bin\utils\staticServer.js:31:45)
    at processTicksAndRejections (internal/process/task_queues.js:85:5) {
  code: 'EADDRINUSE',
  errno: 'EADDRINUSE',
  syscall: 'listen',
  address: '::',

After I modified the port to another port (in the bin files) I got it up and running again. After a while I had to repeat this because I was in the same scenario.

I think not swallowing these errors and logging them might be useful,

For spawned processes:

const child = spawn('node', [join(scullyConfig.homeFolder, './node_modules/.bin/scully'), 'serve'], {
          detached: true,
        })

child.stderr.on('data', err => {
  console.log(err.toString())
})

For express:

angularServerInstance = angularDistServer.listen(scullyConfig.appPort, x => {
      log(
        `Angular distribution server started on "${yellow(
          `http://localhost:${scullyConfig.appPort}/`
        )}" `
      );
    }).on('error', err => {
		console.log(err)
	});

Environment:

  • Windows 10
  • Node.js v12.9.1
  • Angular v9 rc6

from scully.

mgechev avatar mgechev commented on August 24, 2024 2

@SanderElias yes, 0.4.12 includes the fix.

from scully.

mgechev avatar mgechev commented on August 24, 2024 2

I opened a PR to handle path mappings in lazy routes here. The integration test is from the repro that @isaacplmann provided.

Feel free to check this out and tell me if it solves the main problem.

from scully.

isaacplmann avatar isaacplmann commented on August 24, 2024 1

Oops, I missed the first line of getting started that says you need Angular 9.x. I'll upgrade and report back

from scully.

xmlking avatar xmlking commented on August 24, 2024 1

@isaacplmann @vsavkin here is a workaround for nx monorepo compatibility issue
xmlking/yeti@7daffcd
may be @mgechev can help making guess-parser compatible with nx monorepos

from scully.

mgechev avatar mgechev commented on August 24, 2024 1

@isaacplmann yes, the Guess.js parser does did not know how to handle path mappings currently.

@chrisguttandin did some work towards support for Nx monorepos for his angular-prerender.

from scully.

mgechev avatar mgechev commented on August 24, 2024 1

@oleosjo there's another fix that I didn't release yet. Just pushed it in version 0.4.13.

from scully.

jorgeucano avatar jorgeucano commented on August 24, 2024

Can you give me more info?
Can you create a repo for try? i need more description about your environment!

from scully.

isaacplmann avatar isaacplmann commented on August 24, 2024

I get the same error in the scully branch of this repo:
https://github.com/isaacplmann/nx-monorepo-sample/tree/scully

I'm trying to get scully working in an nx monorepo, so maybe there's some hard-coded path that is expecting a default Angular CLI set up?

yarn run v1.19.1
$ scully
Cleaned up /Users/isaac/Documents/code/nx-monorepo-sample/dist/static/ folder.
 ☺   new Angular build imported
started servers in background
Could not connect to server
✨  Done in 17.08s.

from scully.

isaacplmann avatar isaacplmann commented on August 24, 2024

Could be related to lazy-loading routes with tsconfig path aliases.

yarn scully:serve gives this error:

$ scully serve
starting static server...
Could not start Scully serve Error: Scully could not traverse routes

And AppModule loads its routes like this:

  {
    path: 'home',
    loadChildren: () => import('@ng-cli-app/home/ui').then(m => m.HomeUiModule),
    canActivate: [AuthGuard]
  },

from scully.

Splaktar avatar Splaktar commented on August 24, 2024

Possibly related to #31 as I saw this first before I saw the extra info from the errors in that issue.

Update: They appear to be separate issues as that issue isn't seeing any problems with reading the routes.

from scully.

isaacplmann avatar isaacplmann commented on August 24, 2024

I've updated that repo to angular 9 and am still getting the same error. I think guess is having trouble with the lazy loaded routes.

I added a console.log to node_modules/@scullyio/scully/node_modules/guess-parser/dist/guess-parser/index.js

var collectRoutingModules = function (root, registry, result, parentPath, currentPath) {
    if (parentPath === void 0) { parentPath = root; }
    if (currentPath === void 0) { currentPath = ''; }
    console.log('root', root);
    var declaration = registry[root];
    var process = function (r) {
        if (r.module) {

And modified node_modules/@scullyio/scully/bin/routerPlugins/traverseAppRoutesPlugin.js

exports.traverseAppRoutes = async (appRootFolder = config_1.scullyConfig.projectRoot) => {
    try {
        const routes = guess_parser_1.parseAngularRoutes(appRootFolder).map(r => r.path);
        return routes;
    }
    catch (e) {
        console.log('e',e)
        throw new Error('Scully could not traverse routes');
    }
};

And this is what shows up when I run yarn scully:serve:

root /Users/isaac/Documents/code/nx-monorepo-sample/apps/ng-cli-app/src/app/app.module.ts
root /Users/isaac/Documents/code/nx-monorepo-sample/apps/ng-cli-app/src/app/@ng-cli-app/home/ui.ts
e TypeError: Cannot read property 'eagerRoutes' of undefined
    at collectRoutingModules (/Users/isaac/Documents/code/nx-monorepo-sample/node_modules/@scullyio/scully/node_modules/guess-parser/dist/guess-parser/index.js:464:17)
    at processLazyRoute (/Users/isaac/Documents/code/nx-monorepo-sample/node_modules/@scullyio/scully/node_modules/guess-parser/dist/guess-parser/index.js:462:9)
    at Array.forEach (<anonymous>)

from scully.

isaacplmann avatar isaacplmann commented on August 24, 2024

This line /Users/isaac/Documents/code/nx-monorepo-sample/apps/ng-cli-app/src/app/@ng-cli-app/home/ui.ts is obviously not a valid file path.

from scully.

willi84 avatar willi84 commented on August 24, 2024

could be a problem with host (like at angular cli). I had the same. I created a feature request for this:
#87

If you try to manually change the host here in your node_modules, does it work then?

httpGetJson('http://localhost:1864/_pong', {suppressErrors: true})

Do you have an alternative host then localhost on your machine?

from scully.

chrisguttandin avatar chrisguttandin commented on August 24, 2024

Hi everyone, the changes that I made to guess-parser a while ago to support nx monorepos were related to that line: https://github.com/guess-js/guess/blob/master/packages/guess-parser/src/angular/index.ts#L50.

It is using TypeScript's own module resolution and should therefore respect path prefixes like @my-app. We also added a library with a prefix to the test fixture which is why I'm optimistic that it still works.

Right now I don't know of any issues related to nx monorepos when using angular-prerender. But that does of course not guarantee that there are none. :-)

I hope this somehow helps.

from scully.

SanderElias avatar SanderElias commented on August 24, 2024

@mgechev is there a new version of guess-parser released that includes this fix?

from scully.

stewones avatar stewones commented on August 24, 2024

don't know why but started facing the same Could not connect to server. It was all working just fine, I'm not even using nx. already tried a fresh install but no luck.

    "@scullyio/init": "0.0.13",
    "@scullyio/ng-lib": "0.0.9",
    "@scullyio/scully": "0.0.55"

from scully.

oleosjo avatar oleosjo commented on August 24, 2024

I was still having exactly the same problems, but was able to get it working by removing an error check in guess-parser. In my case, I found that the issue was that the guess parser was complaining about multiple root routing modules.

Multiple root routing modules found

I'm not sure why it doesn't like my routes, I only have one root routing module with 'forRoot'. I was able to get it running by commenting out the error check in the relevant function in node_modules/guess-parser/dist/guess-parser/index.js

var findRootModule = function (registry) {
    var childModules = new Set();
    var traverseRoute = function (route) {
        if (route.module) {
            childModules.add(route.module);
        }
        route.children.forEach(traverseRoute);
    };
    var allModulePaths = Object.keys(registry);
    allModulePaths.forEach(function (path) {
        var declaration = registry[path];
        declaration.eagerRoutes.forEach(traverseRoute);
        declaration.lazyRoutes.forEach(traverseRoute);
    });
    var roots = allModulePaths.filter(function (m) { return !childModules.has(m); });
    // if (roots.length > 1) {
    //     throw new Error('Multiple root routing modules found ' + roots.join(', '));
    // }
    return roots[0];
};

The commented out portion is what I modified. It then worked as the first in the array is my root module. However, it still doesn't work with just npm run scully, I have to run npm run scully:serve, that works fine. And then I can run npm run scully and it gives me this message: Background servers already running. servers available and is successful.

Thoughts?

from scully.

xmlking avatar xmlking commented on August 24, 2024

any update on nx workspace support?
I saw some issues closed with nx
But it still don't work for me. to reproduce:
Apply following change here: https://github.com/xmlking/yeti/blob/develop/apps/webapp/src/app/app.module.ts#L23

import('@yeti/home').then(module => module.HomeModule),
// import('../../../../libs/home/src/lib/home.module').then(module => module.HomeModule),
ng build
npx scully 
npx lite-server

from scully.

mgechev avatar mgechev commented on August 24, 2024

@xmlking in home.module.ts you can switch your blog route to:

import('@yeti/blog').then(module => module.BlogModule)

from:

import('../../../blog/src/lib/blog.module').then(
  module => module.BlogModule
)

And everything should work as expected.


If you look at yeti/libs/home/src/index.ts, the relative path you've used is ../../../blog/src/lib/blog.module, TypeScript will try to resolve this relative path to the modules (notice the missing libs directory after yeti):

yeti/blog/src/lib/blog.module.ts
yeti/blog/src/lib/blog.module.tsx
yeti/blog/src/lib/blog.module.d.ts
yeti/blog/src/lib/blog.module/package.json
yeti/blog/src/lib/blog.module/index.ts
yeti/blog/src/lib/blog.module/index.tsx
yeti/blog/src/lib/blog.module/index.d.ts
yeti/blog/src/lib/blog.module.js
yeti/blog/src/lib/blog.module.jsx
yeti/blog/src/lib/blog.module/package.json
yeti/blog/src/lib/blog.module/index.js
yeti/blog/src/lib/blog.module/index.jsx
yeti/blog/src/lib/blog.module/package.json

None of these files exist. I'll detect this earlier in Guess.js and throw an error when the resolved file does not exit.

from scully.

xmlking avatar xmlking commented on August 24, 2024

@mgechev not related to this issue but, I noticed the following error while using typescript 3.7.5 when I run ng build --prod
ng build works fine.

ng build --prod                    
92% chunk asset optimization optimize-css-webpack-pluginAn unhandled exception occurred: Parse error on line 1: 
var(--calendar-width) + var(--calendar-weeknumber-width)var(--cale...
--------------------------------------------------------^
Expecting end of input, "RPAREN", "ADD", "SUB", "MUL", "DIV", got unexpected "FUNCTION"
See "/private/var/folders/ym/_jvkpgm51tq_sbrpmny7qqv00000gn/T/ng-u5Vh1E/angular-errors.log" for further details.

from scully.

xmlking avatar xmlking commented on August 24, 2024

@mgechev I changed as you suggested , still getting error.
I am also locking "guess-parser": "^0.4.13" in my package.json

  "resolutions": {
    "guess-parser": "^0.4.13"
  }

latest changes are on Github, when you get a chance for testing

ng build

ng build  
Generating ES5 bundles for differential loading...
ES5 bundle generation complete.

chunk {polyfills} polyfills-es2015.js, polyfills-es2015.js.map (polyfills) 153 kB [initial] [rendered]
chunk {polyfills-es5} polyfills-es5.js, polyfills-es5.js.map (polyfills-es5) 798 kB [initial] [rendered]
chunk {runtime} runtime-es2015.js, runtime-es2015.js.map (runtime) 9.14 kB [entry] [rendered]
chunk {runtime} runtime-es5.js, runtime-es5.js.map (runtime) 9.13 kB [entry] [rendered]
chunk {main} main-es2015.js, main-es2015.js.map (main) 93.9 kB [initial] [rendered]
chunk {main} main-es5.js, main-es5.js.map (main) 107 kB [initial] [rendered]
chunk {styles} styles-es2015.js, styles-es2015.js.map (styles) 3.41 MB [initial] [rendered]
chunk {styles} styles-es5.js, styles-es5.js.map (styles) 3.41 MB [initial] [rendered]
chunk {yeti-blog} yeti-blog-es2015.js, yeti-blog-es2015.js.map (yeti-blog) 1.46 MB  [rendered]
chunk {yeti-blog} yeti-blog-es5.js, yeti-blog-es5.js.map (yeti-blog) 1.48 MB  [rendered]
chunk {yeti-dashboard} yeti-dashboard-es2015.js, yeti-dashboard-es2015.js.map (yeti-dashboard) 670 kB  [rendered]
chunk {yeti-dashboard} yeti-dashboard-es5.js, yeti-dashboard-es5.js.map (yeti-dashboard) 673 kB  [rendered]
chunk {vendor} vendor-es2015.js, vendor-es2015.js.map (vendor) 6.5 MB [initial] [rendered]
chunk {vendor} vendor-es5.js, vendor-es5.js.map (vendor) 7.61 MB [initial] [rendered]
chunk {yeti-home} yeti-home-es2015.js, yeti-home-es2015.js.map (yeti-home) 1.29 MB  [rendered]
chunk {yeti-home} yeti-home-es5.js, yeti-home-es5.js.map (yeti-home) 1.31 MB  [rendered]
chunk {yeti-admin} yeti-admin-es2015.js, yeti-admin-es2015.js.map (yeti-admin) 335 kB  [rendered]
chunk {yeti-admin} yeti-admin-es5.js, yeti-admin-es5.js.map (yeti-admin) 338 kB  [rendered]
chunk {common} common-es2015.js, common-es2015.js.map (common) 10.8 kB  [rendered]
chunk {common} common-es5.js, common-es5.js.map (common) 11.5 kB  [rendered]
chunk {yeti-not-found} yeti-not-found-es2015.js, yeti-not-found-es2015.js.map (yeti-not-found) 6.65 kB  [rendered]
chunk {yeti-not-found} yeti-not-found-es5.js, yeti-not-found-es5.js.map (yeti-not-found) 8.07 kB  [rendered]
Date: 2020-01-20T01:11:46.244Z - Hash: a5ea7ea12f9534809a9f - Time: 14192ms

npx scully

npx scully
Cleaned up /Users/schintha/Developer/Work/SPA/yeti/dist/static/apps/webapp folder.
 ☺   new Angular build imported
 ☺   Started servers in background
Could not connect to server

from scully.

xmlking avatar xmlking commented on August 24, 2024

npx scully only works when I change all routes form
loadChildren: () => import('@yeti/blog').then(module => module.BlogModule)
format to
loadChildren: () => import('../../../blog/src/lib/blog.module').then(module => module.BlogModule)

          {
            path: 'blog',
            loadChildren: () =>
            import('../../../blog/src/lib/blog.module').then(module => module.BlogModule)
          }

from scully.

mgechev avatar mgechev commented on August 24, 2024

@xmlking I wasn't able to reproduce the route parsing error when using path mapping. For me things keep working with @yeti/blog, etc. as well.

Folks who hit the parsing error can directly report to https://github.com/guess-js/guess with a repro.

from scully.

xmlking avatar xmlking commented on August 24, 2024

Sorry to bring this issue back, may be this issue is related to my env
I am getting following error after upgrading to the latest version:

ng build

yarn run scully --showGuessError

yarn run v1.21.1
$ scully --showGuessError
Cleaned up /Users/xyz/Developer/Work/SPA/yeti/dist/static/apps/webapp folder.
 ☺   new Angular build imported
 ☺   Started servers in background
servers available
Finding all routes in application.
TypeError: Cannot read property 'eagerRoutes' of undefined
    at collectRoutingModules (/Users/xyz/Developer/Work/SPA/yeti/node_modules/guess-parser/dist/guess-parser/index.js:465:17)
    at processLazyRoute (/Users/xyz/Developer/Work/SPA/yeti/node_modules/guess-parser/dist/guess-parser/index.js:463:9)
    at Array.forEach (<anonymous>)
    at collectRoutingModules (/Users/xyz/Developer/Work/SPA/yeti/node_modules/guess-parser/dist/guess-parser/index.js:466:28)
    at Object.exports.parseRoutes [as parseAngularRoutes] (/Users/xyz/Developer/Work/SPA/yeti/node_modules/guess-parser/dist/guess-parser/index.js:598:9)
    at Object.exports.traverseAppRoutes (/Users/xyz/Developer/Work/SPA/yeti/node_modules/@scullyio/scully/routerPlugins/traverseAppRoutesPlugin.js:16:33)
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
    at async Object.exports.generateAll (/Users/xyz/Developer/Work/SPA/yeti/node_modules/@scullyio/scully/utils/defaultAction.js:21:33)

We encountered a problem while reading the routes from your applications source.
This might happen when there are lazy-loaded routes, that are not loaded,
Or when there are paths we can not resolve statically.
Check the routes in your app, rebuild and retry.
(You can inspect the error by passing the --showGuessError flag

When there are extraRoutes in your config, we will still try to render those.




We did not find an empty route ({path:'', component:rootComponent}) in your app.
This means that the root of your application will be you normal angular app, and
is not rendered by Scully
In some circumstances this can be cause because a redirect like:
   ({path: '', redirectTo: 'home', pathMatch: 'full'})
is not picked up by our scanner.

By adding '' to the extraRoutes array in the scully.config option, you can bypass this issue


No routes found in application, are you sure you installed the router? Terminating.
error Command failed with exit code 15.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
ng version

     _                      _                 ____ _     ___
    / \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
   / △ \ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |
  / ___ \| | | | (_| | |_| | | (_| | |      | |___| |___ | |
 /_/   \_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
                |___/
    

Angular CLI: 9.0.0-rc.10
Node: 13.5.0
OS: darwin x64

Angular: 9.0.0-rc.10
... animations, cli, common, compiler, compiler-cli, core, forms
... language-service, localize, platform-browser
... platform-browser-dynamic, router, service-worker
Ivy Workspace: Yes

Package                           Version
-----------------------------------------------------------
@angular-devkit/architect         0.803.23
@angular-devkit/build-angular     0.900.0-rc.10
@angular-devkit/build-optimizer   0.900.0-rc.10
@angular-devkit/build-webpack     0.803.23
@angular-devkit/core              8.3.23
@angular-devkit/schematics        8.3.23
@angular/cdk                      9.0.0-rc.8
@angular/fire                     5.3.0
@ngtools/webpack                  9.0.0-rc.10
@schematics/angular               9.0.0-rc.9
@schematics/update                0.900.0-rc.10
rxjs                              6.5.4
typescript                        3.7.5
webpack                           4.41.2
    

from scully.

SanderElias avatar SanderElias commented on August 24, 2024

@xmlking You have an issue with the Guess parser.
Please make a minimal reproduction, and use that to file an issue as @mgechev said above.

from scully.

mgechev avatar mgechev commented on August 24, 2024

@xmlking also make sure you're using the latest release of Guess.js. I released yesterday.

from scully.

ohabash avatar ohabash commented on August 24, 2024

Im in an nx repo and i was not able to find a solution above. Although im not sure this is caused by NX incompatibility cause sometimes it works and others it doesnt. Maybe someone can advise?

cmd

npx scully --project habitat-commons --verbose --ssl --ssl-cert=./certs/cert.pem --ssl-key=./certs/key.pem

output

Screen Shot 2022-03-24 at 2 48 18 PM

scully Config

import { ScullyConfig } from '@scullyio/scully';

/** this loads the default render plugin, remove when switching to something else. */


export const config: ScullyConfig = {
  projectRoot: './apps/habitat-commons/src',
  projectName: 'habitat-commons',
  spsModulePath: 'YOUR OWN MODULE PATH HERE',
  outDir: './dist/static',
  appPort: 2010,
  staticPort: 2011,
  reloadPort: 2012,
  routes: {},
};

ng routing file

import { NgModule } from "@angular/core";
import { Routes, RouterModule } from "@angular/router";
import { PagesComponent } from '@habitat-commons-nx/layout';
import { HomePageComponent } from "./home-page/home-page.component";
import { ServiceTemplateComponent } from '@habitat-commons-nx/layout';

const routes: Routes = [
  { path: '', component: HomePageComponent, pathMatch: 'full', },
  { path: 'page/:page', component: PagesComponent, },
  { path: 'services/:slug', component: ServiceTemplateComponent, },
];

@NgModule({
  imports: [
    RouterModule.forRoot(routes, { scrollPositionRestoration: 'enabled' }),
  ],
  exports: [RouterModule],
})
export class habitatRoutingModule {}

env

Node : 14.16.0
OS   : darwin x64
npm  : 6.14.11
nx : 13.8.4
@nrwl/angular : 13.8.4
@nrwl/cli : 13.8.4
@nrwl/cypress : 13.8.4
@nrwl/detox : undefined
@nrwl/devkit : 13.8.4
@nrwl/eslint-plugin-nx : 13.8.4
@nrwl/express : 13.9.2
@nrwl/jest : 13.8.4
@nrwl/js : 13.9.2
@nrwl/linter : 13.8.4
@nrwl/nest : undefined
@nrwl/next : undefined
@nrwl/node : 13.9.2
@nrwl/nx-cloud : 13.1.6
@nrwl/react : undefined
@nrwl/react-native : undefined
@nrwl/schematics : undefined
@nrwl/storybook : 13.8.4
@nrwl/tao : 13.8.4
@nrwl/web : undefined
@nrwl/workspace : 13.8.4
typescript : 4.5.5
rxjs : 6.6.7
---------------------------------------
Community plugins:
@angular/animations: 13.2.5
@angular/cdk: 13.2.5
@angular/common: 13.2.5
@angular/compiler: 13.2.5
@angular/core: 13.2.5
@angular/fire: 7.2.1
@angular/forms: 13.2.5
@angular/google-maps: 13.3.0
@angular/material: 13.2.5
@angular/platform-browser: 13.2.5
@angular/platform-browser-dynamic: 13.2.5
@angular/platform-server: 13.2.5
@angular/router: 13.2.5
@fortawesome/angular-fontawesome: 0.9.0
@nguniversal/express-engine: 13.0.2
@scullyio/init: 2.1.26
@angular-devkit/build-angular: 13.2.5
@angular/cli: 13.3.0
@angular/compiler-cli: 13.2.5
@angular/language-service: 13.2.5
@ngneat/tailwind: 7.0.3
@storybook/angular: 6.4.19

from scully.

Related Issues (20)

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.