mrmlnc / fast-glob Goto Github PK
View Code? Open in Web Editor NEW:rocket: It's a very fast and efficient glob library for Node.js
License: MIT License
:rocket: It's a very fast and efficient glob library for Node.js
License: MIT License
Since v2.0.0 an error is thrown when run on a filesystem. Number of files/dirs is 54/18 in my case.
Call stack:
yarn run v1.3.2
$ OVERRIDE_ENV=development npm run build
> [email protected] build /home/max/Development/example/packages/app
> APP_RELEASE=$(git describe --always) NODE_ENV=production node build/build.js
/home/max/Development/example/node_modules/fast-glob/out/providers/reader-sync.js:40
throw err;
^
RangeError: Maximum call stack size exceeded
at call.safe (/home/max/Development/example/node_modules/readdir-enhanced/lib/stat.js:26:26)
at onceWrapper (/home/max/Development/example/node_modules/readdir-enhanced/lib/call.js:45:17)
at onceWrapper (/home/max/Development/example/node_modules/readdir-enhanced/lib/call.js:45:17)
at exports.lstat (/home/max/Development/example/node_modules/readdir-enhanced/lib/sync/fs.js:59:5)
at Object.safeCall [as safe] (/home/max/Development/example/node_modules/readdir-enhanced/lib/call.js:24:8)
at stat (/home/max/Development/example/node_modules/readdir-enhanced/lib/stat.js:19:8)
at DirectoryReader.processItem (/home/max/Development/example/node_modules/readdir-enhanced/lib/directory-reader.js:171:5)
at array.forEach.item (/home/max/Development/example/node_modules/readdir-enhanced/lib/sync/for-each.js:14:5)
at Array.forEach (<anonymous>)
at Object.syncForEach [as forEach] (/home/max/Development/example/node_modules/readdir-enhanced/lib/sync/for-each.js:13:9)
at call.safe (/home/max/Development/example/node_modules/readdir-enhanced/lib/directory-reader.js:80:16)
at onceWrapper (/home/max/Development/example/node_modules/readdir-enhanced/lib/call.js:45:17)
at onceWrapper (/home/max/Development/example/node_modules/readdir-enhanced/lib/call.js:45:17)
at exports.readdir (/home/max/Development/example/node_modules/readdir-enhanced/lib/sync/fs.js:19:5)
at Object.safeCall [as safe] (/home/max/Development/example/node_modules/readdir-enhanced/lib/call.js:24:8)
at DirectoryReader.readNextDirectory (/home/max/Development/example/node_modules/readdir-enhanced/lib/directory-reader.js:71:10)
npm ERR! Linux 4.14.14-300.fc27.x86_64
npm ERR! argv "/usr/bin/node" "/home/max/.config/yarn/global/node_modules/.bin/npm" "run" "build"
npm ERR! node v9.4.0
npm ERR! npm v3.10.10
npm ERR! code ELIFECYCLE
npm ERR! [email protected] build: `APP_RELEASE=$(git describe --always) NODE_ENV=production node build/build.js`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] build script 'APP_RELEASE=$(git describe --always) NODE_ENV=production node build/build.js'.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the app package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR! APP_RELEASE=$(git describe --always) NODE_ENV=production node build/build.js
npm ERR! You can get information on how to open an issue for this project with:
npm ERR! npm bugs app
npm ERR! Or if that isn't available, you can get their info via:
npm ERR! npm owner ls app
npm ERR! There is likely additional logging output above.
npm ERR! Please include the following file with any support request:
npm ERR! /home/max/Development/example/packages/app/npm-debug.log
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
Looks to be related to readdir-enhanced
.
fast-glob
runs without any error thrown.
fast-glob
.const fastGlob = require('fast-glob');
const paths = fastGlob.sync([
path.join(__dirname, './**/*.html'),
path.join(__dirname, './**/*.js'),
]);
Since v2.0.0 has removed bashNative mode, I'm actually going to pin my fast-glob
version to 1.0.1 anyway since I want that native level of performance. That was actually the reason why I started using fast-glob in the first place!
something like
a/b/c
d/e/f/g
h
with depth 2
will only get
a/b
d/e
h
It'd be nice to have the ability to run a callback on every file, something like this:
fastGlob('sources/*', filename => {
// do some asynchronous stuff
}).then(filenames => {
console.log('done')
})
Not implemented
I'm building a search for 50k files on a network share and each query takes about 10s.
It would be nice to cancel requests if the user changes his input. Is this possible?
Would be cool to provide ability to return tasks
from the package. Something like:
import * as fg from 'fast-glob';
const tasks = fg.getTasks(['pattern1', 'pattern2'], options);
Maybe also we need think about ability to import tasks instead of patterns:
import * as fg from 'fast-glob';
const tasks = fg.sync([task1, task2], options);
Hi! I'm seeing a fail on Windows related to micromatch/micromatch#95 (comment) and path.sep
. Does this sound like something fast-glob is doing?
The error stack is:
C:\projects\esm\node_modules\snapdragon\lib\parser.js:473
throw new Error('no parsers registered for: "' + self.input.slice(0, 5) + '"');
^
.cac": no parsers registered for: "
at parse (C:\projects\esm\node_modules\snapdragon\lib\parser.js:473:15)
at Parser.parse (C:\projects\esm\node_modules\snapdragon\lib\parser.js:477:24)
at Snapdragon.parse (C:\projects\esm\node_modules\snapdragon\index.js:122:28)
at Snapdragon.<anonymous> (C:\projects\esm\node_modules\fast-glob\node_modules\micromatch\lib\utils.js:47:45)
at parse (C:\projects\esm\node_modules\fast-glob\node_modules\micromatch\index.js:741:26)
at memoize (C:\projects\esm\node_modules\fast-glob\node_modules\micromatch\index.js:861:13)
at Function.micromatch.parse (C:\projects\esm\node_modules\fast-glob\node_modules\micromatch\index.js:747:10)
at create (C:\projects\esm\node_modules\fast-glob\node_modules\micromatch\index.js:688:44)
at C:\projects\esm\node_modules\fast-glob\node_modules\micromatch\index.js:697:16
at memoize (C:\projects\esm\node_modules\fast-glob\node_modules\micromatch\index.js:861:13)
npm ERR! Test failed. See above for more details.
Check cmd performance.
macOS 10.13.2
9.4.0
Don't read
fixtures/nested/file.txt
Pattern:
fixtures/*/*.txt
The directory should be read.
Double-negative options is a bad developer experience. It's better to just invert the default.
nobrace
=> brace
noglobstar
=> globstar
noext
=> ext
(Or Maybe even extension
to be totally clear)
nocase
=> case
I realize these are brought over from node-glob
, but we can do better.
With the following directory tree:
+-- test/
| +-- dir
| +-- file.js
fg.sync('test/**', {onlyFiles: false, markDirectories: false});
// Result => ['test/dir/', 'test/dir/file.js']
// Should be => ['test/dir', 'test/dir/file.js']
fg.sync('test/**', {onlyFiles: false, markDirectories: true});
// Result => ['test/dir//', 'test/dir/file.js']
// Should be => ['test/dir/', 'test/dir/file.js']
macOS 10.13.3
8.9.0
We have to figure out a way to reduce the initialization time of filters. Something like 14ms for the following tasks:
{ base: 'src/types/one',
dynamic: true,
patterns: [ 'src/types/one/*/sub/y/y.json' ],
positive: [ 'src/types/one/*/sub/y/y.json' ],
negative: [] }
Prepare reader options: 8.445ms
{ base: 'src/types/two',
dynamic: true,
patterns: [ 'src/types/two/*/sub/y/y.json' ],
positive: [ 'src/types/two/*/sub/y/y.json' ],
negative: [] }
Prepare reader options: 1.802ms
{ base: 'src/types/three',
dynamic: true,
patterns: [ 'src/types/three/*/sub/y/y.json' ],
positive: [ 'src/types/three/*/sub/y/y.json' ],
negative: [] }
Prepare reader options: 1.400ms
{ base: 'src/types/four',
dynamic: true,
patterns: [ 'src/types/four/*/sub/y/y.json' ],
positive: [ 'src/types/four/*/sub/y/y.json' ],
negative: [] }
Prepare reader options: 0.794ms
{ base: 'src/types/five',
dynamic: true,
patterns: [ 'src/types/five/*/sub/y/y.json' ],
positive: [ 'src/types/five/*/sub/y/y.json' ],
negative: [] }
Prepare reader options: 2.111ms
10.13.3 (macOS)
9.5.0
We excluding from reading any entries that match to the negative pattern, even directories.
FIXTURES NODE_GLOB FAST_GLOB
---------------------------------------- --------- ---------
fixtures/first/file.md + -
fixtures/first/nested + -
fixtures/first/nested/directory + -
fixtures/first/nested/directory/file.md + -
fixtures/first/nested/file.md + -
fixtures/second/file.md + -
fixtures/second/nested + -
fixtures/second/nested/directory + -
fixtures/second/nested/directory/file.md + -
fixtures/second/nested/file.md + -
We shouldn't excluding from reading directories when the positive patterns has more then one accepted depth level.
FIXTURES NODE_GLOB FAST_GLOB
---------------------------------------- --------- ---------
fixtures/first/file.md + +
fixtures/first/nested + +
fixtures/first/nested/directory + +
fixtures/first/nested/directory/file.md + +
fixtures/first/nested/file.md + +
fixtures/second/file.md + +
fixtures/second/nested + +
fixtures/second/nested/directory + +
fixtures/second/nested/directory/file.md + +
fixtures/second/nested/file.md + +
fixtures/
├── file.md
├── first
│ ├── file.md
│ └── nested
│ ├── directory
│ │ └── file.md
│ └── file.md
└── second
├── file.md
└── nested
├── directory
│ └── file.md
└── file.md
const entries = fg.sync(['fixtures/**', '!fixtures/*']);
console.log(entries);
With the following directory tree:
+-- test/
| +-- dir
| +-- file.js
fg.sync('test/**', {onlyFiles: false});
// Result => ['test/dir/', 'test/dir/file.js']
// Should be => ['test', 'test/dir', 'test/dir/file.js']
For example with node-glob
:
glob.sync('test/**', {nodir: false});
// Result => ['test', 'test/dir', 'test/dir/file.js']
I have some instances where the glob pattern is not a glob at all and is a path to a directory/file.
Example
const glob = require("fast-glob");
glob.sync("node_modules/zone.js");
Error
Maximum call stack size exceeded
I expect that this doesn't break and return the path.
We need to introduce smoke tests.
Now the package has some bugs that we don't even know about. We need to introduce the test of comparison with node-glob
.
I have an issue that if my glob pattern is
src/**/*.html
And the file is directly under src/index.html
it is not being captured.
Code:
return sync("src/**/*.html", { bashNative: [] });
My OS is OS Sierra.
Errors are being swallowed here:
fast-glob/src/providers/reader-sync.ts
Line 28 in af7ba6f
I had a:
ENOENT: no such file or directory, lstat '/dev/fd/12'
but the err.prev
was:
EBADF: bad file descriptor, lstat '/dev/fd/12'
Admittedly, I am using the memfs
and unionfs
. Perhaps the prev
is unique to their custom Error object. But maybe there should be a {throwErrors}
option?
const glob = require('fast-glob');
const nodeGlob = require('glob');
const {Volume} = require('../lib/volume');
const {patchFs} = require('fs-monkey');
const {ufs} = require('unionfs');
const fs = require('fs');
var readdir = require('readdir-enhanced');
let vol
function start() {
vol = new Volume()
ufs.use(fs).use(vol);
patchFs(ufs)
}
start()
function reset() {
vol.reset()
}
vol.writeFileSync('/app/foo.json', 'foo')
glob.sync('/app')
vol.symlinkSync('/app', '/app/foo')
glob.sync('/app') // This is empty array.
nodeGlob.sync('/app/**') // Works
Ignore patterns don't work in ignore
option.
Ignore patterns should be work in ignore
option. node-glob
works perfect.
file.txt
with any contents.file.yaml
with any contents.const fg = require('fast-glob');
fg(['**/*'], {
absolute: true,
dot: true,
ignore: [`!{**/*,*}.txt`],
onlyFiles: true
})
.then((entries) => console.log(entries));
See benchmark file: https://gist.github.com/pvdlg/8f72824d81263efc71b30fd443aa8b0e
npm install matcha, fast-glob, glob
./node_modules/.bin/matcha fast-blog-bench.js
'a/*'
, ignore: ['a']
231 op/s » fast-glob sync
136 op/s » glob sync
'a/*'
, ignore: ['a/**']
302 op/s » fast-glob sync
31,096 op/s » glob sync
It's quite an edge case as it seems the performance difference happens only when the the ignore
pattern make so that no pattern will match. It seems that node-glob
is able to figure out that nothing will ever with pattern 'a/*'
and ignore ['a/**']
, while fast-glob
still goes through the directory.
With pattern 'a/*'
and ignore ['a']
it seems neither fast-glob
nor node-glob
figure out that nothing would match and both attempt to go through the directory.
I thought the directory would be ignored completely in such case.
I'm not sure it's a big issue as it concerns a pattern/ignore config that doesn't make much sense, but I though it worth mentioning in case the perf improvement is really simple to do. Maybe ignoring patterns that are included within ignore pattern can bring other more useful performance improvements.
When I tried to use this on Windows with an absolute path, it appends the cwd to the absolute path
fastGlob.sync("C:/foo/*.bar");
Causes
Error: ENOENT: no such file or directory, scandir 'C:\my\current\working\dir\C:\foo'
10.13.3 (macOS)
9.5.0
Where we set the cwd
option, the packages
path is passed to the depth filter and this is matched to the *
negative pattern. After that, we do not read this directory.
If you pass patterns without cwd
option (like app/**/node_modules/**
), then we work with app/packages
and it's works fine.
[]
[
'packages/bar/node_modules',
'packages/bar/node_modules/baz',
'packages/bar/node_modules/baz/c.json',
'packages/bar/node_modules/baz/node_modules',
'packages/bar/node_modules/baz/node_modules/d.json',
'packages/bar/node_modules/baz/node_modules/something'
]
app
└── packages
├── bar
│ ├── b.json
│ └── node_modules
│ └── baz
│ ├── c.json
│ └── node_modules
│ ├── d.json
│ └── something
└── foo
└── a.json
const globby = require('globby');
const fg = require('fast-glob');
const fgNext = require('../../OpenSource/fast-glob');
const entries1 = globby.sync(['**/node_modules/**', '!*'], { cwd: 'app', nodir: false });
const entries2 = fg.sync(['**/node_modules/**', '!*'], { cwd: 'app', onlyFiles: false });
const entries3 = fgNext.sync(['**/node_modules/**', '!*'], { cwd: 'app', onlyFiles: false });
console.log('GLOBBY@7', entries1); // Expected behaviour
console.log('FAST-GLOB@2', entries2); // []
console.log('FAST-GLOB@NEXT', entries3); // []
I've written a gulp-like file transformer to glob for files, read them, modify them, and write them back to the file system. I've also included delete functionality. As this functionality can be highly dangerous when there's a bug, I test using mock-fs
.
I had been using globby
, but switched to using fast-glob directly. When I was using globby v7 (backed by node-glob) I was able to use mock-fs. Now, using fast-glob, I get ENOENT errors thrown.
Allow file-system to be mocked for testing using something like mock-fs
or by passing a mock file system object to fast-glob as an option.
fs.scandir
from nodejs/node#15699. Most likely it will give double performance increase for work with FS (not on all platforms). Right now I can use the scandir-native
package, but this is native module and it requires compilation.readdir-enhanced
is poorly maintained (code, architecture).Would be cool to include debug for filters, providers and other places. This will help catching bugs easier.
bash-glob
with **/*
-> micromatch
-> result
const matches = await fg(['../files/foo.json', '../files/bar.json']);
console.log(matches);
// Output: [ ]
const matches = await fg(['../files/foo.json', '../files/bar.json']);
console.log(matches);
// Output: ['../files/foo.json', '../files/bar.json']
When we work with static patterns, we use the **
pattern. Unfortunately, this does not cover cases with relative paths. We have to work with real patterns.
bash-glob
(many questions)fs.readdir
fs.scandir
instead of fs.readdir
+ fs.stat
fs.scandir
then create (scandir|readdir)-native
package~~ (native package is a bad idea)inode
for fs.stats
calls with stats
optionnode_modules
) during the scanglobby
tartifacts
2.0.0
to npmfast-glob
previous version in the benchmark@types/readdir-enhanced
It appears that there is a limit somewhere? Can you confirm?
It's impossible to mitigate a negate pattern with a positive one. Commit 8ce21ee breaks previous behavior.
> fg.sync(['src/*', 'src/foo/**'], { cwd, ignore: ['**/foo/**'] })
[ 'src/index.js' ]
> fg.sync(['src/*', 'src/foo/**'], { cwd, ignore: ['**/foo/**'] })
[ 'src/index.js', 'src/foo/bar.js' ]
There is simple folders tree:
src
├── foo
│ └── bar.js
└── index.js
I want to have both files - index.js
and bar.js
. Also, i have negate pattern **/foo/**
.
I started getting this error when updating from node 6 to node 8. I can reproduce running this code on my large repository but I haven't yet tracked it down to which files are exactly causing it:
const glob = require('fast-glob');
const files = glob.sync('**/*.js', {
bashNative: [],
onlyFiles: true,
cwd: process.cwd(),
ignore: ['node_modules/**'],
});
console.log(files);
FATAL ERROR: v8::ToLocalChecked Empty MaybeLocal.
1: node::Abort() [/usr/local/bin/node]
2: node::FatalException(v8::Isolate*, v8::Local<v8::Value>, v8::Local<v8::Message>) [/usr/local/bin/node]
3: v8::V8::ToLocalEmpty() [/usr/local/bin/node]
4: node::ReadDir(v8::FunctionCallbackInfo<v8::Value> const&) [/usr/local/bin/node]
5: v8::internal::FunctionCallbackArguments::Call(void (*)(v8::FunctionCallbackInfo<v8::Value> const&)) [/usr/local/bin/node]
6: v8::internal::MaybeHandle<v8::internal::Object> v8::internal::(anonymous namespace)::HandleApiCallHelper<false>(v8::internal::Isolate*, v8::internal::Handle<v8::internal::HeapObject>, v8::internal::Handle<v8::internal::HeapObject>, v8::internal::Handle<v8::internal::FunctionTemplateInfo>, v8::internal::Handle<v8::internal::Object>, v8::internal::BuiltinArguments) [/usr/local/bin/node]
7: v8::internal::Builtin_Impl_HandleApiCall(v8::internal::BuiltinArguments, v8::internal::Isolate*) [/usr/local/bin/node]
8: 0x2b0d0ee0463d
9: 0x2b0d0eef474a
node v8.9.3, macOS 10.13.2
So, welcome to the family.
We need fix performance for the micromatch
package.
So, we spend about 30ms (for 400 entries with 50 depth) to find the regular expression for the pattern in the cache when we pass options. Proof:
Before:
fast-glob-current.js
(TIME) 81.862ms ±2.573% | (MEMORY) 8.357MB ±0.081% | Entries: 200 | Errors: 0 | Retries: 1
fast-glob-previous.js
(TIME) 60.310ms ±1.405% | (MEMORY) 10.533MB ±0.073% | Entries: 200 | Errors: 0 | Retries: 1
After (Transform patterns to RegExps once in Reader
class):
P.S: You need to look at the diff between numbers.
Glob works fine when I force it to not use bashNative via { bashNative: [] }
, but fails otherwise
events.js:160
throw er; // Unhandled 'error' event
^
Error: spawn /usr/local/bin/bash ENOENT
at exports._errnoException (util.js:1018:11)
at Process.ChildProcess._handle.onexit (internal/child_process.js:193:32)
at onErrorNT (internal/child_process.js:367:16)
at _combinedTickCallback (internal/process/next_tick.js:80:11)
at process._tickCallback (internal/process/next_tick.js:104:9)
This is on OSX
When searching for a single file (no glob parts in the path), the time increase with as the number of files in the same directory increase. With node-glob
this time is constant.
Find 1 file in a directory with 1 file (ran 500 times):
Find 1 file in a directory with 500 file (ran 500 times):
Find 1 file in a directory with 2000 file (ran 500 times):
Globbing a static path (with no wildcards) is a something that can happen sometimes in modules that get the glob patterns from user input, as users can pass a list of file path (e.g, mymodule file1.js file2.js file3.js
).
It seems that node-glob
has a way to detect those cases and optimize them. There is potential gain of perf in fast-glob
by implementing the same type of optimization.
Use the code below and change the TOTAL_FILES
to measure the changes in the globbing time between fast-glob
and node-glob
.
const fs = require('fs');
const path = require('path');
const glob = require('glob');
const fg = require('fast-glob');
const TOTAL_FILES = 2000;
fs.mkdirSync('test')
for (let i = 0; i < TOTAL_FILES; i++) {
const filepath = path.join('test', `file-${i}`);
fs.writeFileSync(filepath, '');
}
console.time('node-glob');
for (let i = 0; i < 500; i++) {
glob.sync('test/file-1')
}
console.timeEnd('node-glob');
console.time('fast-glob');
for (let i = 0; i < 500; i++) {
fg.sync('test/file-1')
}
console.timeEnd('fast-glob');
Say you want to find all node_modules
folders, but not node_modules
folders nested inside them.
E.g.
- app
- packages
- foo
- bar
- node_modules <- Return this and don't search anything inside it.
- baz
- node_modules <- Don't return this, and don't even search it.
Can this be done with fast-glob?
It is impossible with node-glob
, but would be cool if it were possible in fast-glob
.
Well, after release https://github.com/BigstickCarpet/readdir-enhanced/blob/master/CHANGELOG.md#v150-2017-04-10 we can create cache for directories. This can improve the performance and search speed of files by several times.
Just for fun. To compare the performance with the following solutions:
ls
ripgrep
python.glob
(and etc.)10.13.3 (macOS)
9.5.0
['fixtures/directory']
[]
fixtures/
├── directory
├── file.md
└── file.txt
const entries1 = globby.sync(['fixtures/directory', '!fixtures/**', '!fixtures/directory'], { nodir: false });
const entries2 = fg.sync(['fixtures/directory', '!fixtures/**', '!fixtures/directory'], { onlyFiles: false });
console.log('GLOBBY@7', entries1); // []
console.log('FAST-GLOB@2', entries2); // ['fixtures/directory']
First thanks a lot for this package. It's much faster than node-glob
with a much lower memory usage!
One issue I faced while migrating is that node-glob
skips all folders that start with a dot, probably in case they're not traversable. fast-glob
doesn't skip them which can lead to permission issues like Error: EACCES: permission denied, scandir 'test/.foo'
(fails the whole scan).
This can be fixed using:
fastGlob(pattern, {
deep: stats => stats.path.charAt(0) !== '.'
})
Maybe you could document this in the README in the Compatible with node-glob
section?
git clone https://github.com/sindresorhus/globby
npm install
node -e "const fg = require('fast-glob'); fg.sync('**/index.js')"
FATAL ERROR: v8::ToLocalChecked Empty MaybeLocal.
1: node::Abort() [/usr/local/bin/node]
2: node::OnFatalError(char const*, char const*) [/usr/local/bin/node]
3: v8::Utils::ReportApiFailure(char const*, char const*) [/usr/local/bin/node]
4: node::ReadDir(v8::FunctionCallbackInfo<v8::Value> const&) [/usr/local/bin/node]
5: v8::internal::FunctionCallbackArguments::Call(void (*)(v8::FunctionCallbackInfo<v8::Value> const&)) [/usr/local/bin/node]
6: v8::internal::MaybeHandle<v8::internal::Object> v8::internal::(anonymous namespace)::HandleApiCallHelper<false>(v8::internal::Isolate*, v8::internal::Handle<v8::internal::HeapObject>, v8::internal::Handle<v8::internal::HeapObject>, v8::internal::Handle<v8::internal::FunctionTemplateInfo>, v8::internal::Handle<v8::internal::Object>, v8::internal::BuiltinArguments) [/usr/local/bin/node]
7: v8::internal::Builtin_Impl_HandleApiCall(v8::internal::BuiltinArguments, v8::internal::Isolate*) [/usr/local/bin/node]
8: 0x11e5eea842fd
When excluding node_modules
it works as expected:
node -e "const fg = require('fast-glob'); fg.sync('**/index.js', {ignore: 'node_modules'})"
With async function is also works:
node -e "const fg = require('fast-glob'); fg('**/index.js', {ignore: 'node_modules'}).then(console.log)"
To return the index.js
file and not errors out.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.