8eecf0d2 / netlify-local Goto Github PK
View Code? Open in Web Editor NEWLocal Netlify service emulation
Local Netlify service emulation
This is a pretty insane feature considering what it's called, what it's actually capable of, and how it's implemented...
Notice: It's confusing and important to understand if the "redirect rule" in question is a true 3xx
style redirect or a more fancy rewrite.
The main features to implement:
build.publish
)Netlify will return status code 301
for what it calls basic redirects.
Netlify will perform a rewrite if a status code is set and not equal to 301
, 302
, 303
.
By default Netlify will serve a 404.html
file if it's provided and no redirect rules or static files match the path.
404.html
I'm not even gonna bother with this yet...
Basically param swapping between from
and to
- should be easy enough to implement with express and a url pattern library.
from = "/:partA/:partB"
to = "/:partB/:partA"
# "/foo/bar" → "/bar/foo"
Similar to placeholders except the *
and :splat
param are bound.
More or less states that query params can be used as placeholders, the syntax is weird but toml
is luckily more readable that Netlify's _redirect
file formatting.
These feature are getting way beyond my personal use cases - plus I don't see them being entirely useful for local development, it'd be great to support them but I'm not holding my breath.
I'm not entirely sure if there are any special quirks when it comes to Netlify's static file serving but I'm guessing there are - would be good to list them and start implementing if within scope.
For whatever reason cli defaults don't work.
The following commands should all return the same result.
netlify-local
netlify-local -n netlify.toml
netlify-local -w webpack.config.js
netlify-local -n netlify.toml -w webpack.config.js
It can be quite helpful to do repo installs
$ npm -g i '8eecf0d2/netlify-local'
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: [email protected] (node_modules/netlify-local/node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for [email protected]: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})
npm ERR! path /usr/local/lib/node_modules/netlify-local/.dist/cli.js
npm ERR! code ENOENT
npm ERR! errno -2
npm ERR! syscall chmod
npm ERR! enoent ENOENT: no such file or directory, chmod '/usr/local/lib/node_modules/netlify-local/.dist/cli.js'
npm ERR! enoent This is related to npm not being able to find a file.
npm ERR! enoent
npm ERR! A complete log of this run can be found in:
npm ERR! /root/.npm/_logs/2018-12-12T13_20_46_337Z-debug.log
Tail of the debug log
10944 info linkStuff [email protected]
10945 silly linkStuff [email protected] has /usr/local/lib/node_modules/netlify-local/node_modules as its parent node_modules
10946 silly linkStuff [email protected] is part of a global install
10947 silly linkStuff [email protected] is installed into a global node_modules
10948 verbose linkBins [ { webpack: './bin/webpack.js' },
10948 verbose linkBins '/usr/local/lib/node_modules/netlify-local/node_modules/.bin',
10948 verbose linkBins false ]
10949 silly build [email protected]
10950 info linkStuff [email protected]
10951 silly linkStuff [email protected] has /usr/local/lib/node_modules as its parent node_modules
10952 silly linkStuff [email protected] is part of a global install
10953 silly linkStuff [email protected] is installed into a global node_modules
10954 silly linkStuff [email protected] is installed into the top-level global node_modules
10955 verbose linkBins [ { 'netlify-local': '.dist/cli.js' }, '/usr/local/bin', true ]
10956 timing action:build Completed in 126ms
10957 verbose unlock done using /root/.npm/_locks/staging-3a08f0df5026584d.lock for /usr/local/lib/node_modules/.staging
10958 timing stage:rollbackFailedOptional Completed in 652ms
10959 timing stage:runTopLevelLifecycles Completed in 46801ms
10960 warn optional SKIPPING OPTIONAL DEPENDENCY: [email protected] (node_modules/netlify-local/node_modules/fsevents):
10961 warn notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for [email protected]: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})
10962 verbose notsup SKIPPING OPTIONAL DEPENDENCY: Valid OS: darwin
10962 verbose notsup SKIPPING OPTIONAL DEPENDENCY: Valid Arch: any
10962 verbose notsup SKIPPING OPTIONAL DEPENDENCY: Actual OS: linux
10962 verbose notsup SKIPPING OPTIONAL DEPENDENCY: Actual Arch: x64
10963 verbose stack Error: ENOENT: no such file or directory, chmod '/usr/local/lib/node_modules/netlify-local/.dist/cli.js'
10964 verbose cwd /root
10965 verbose Linux 4.19.7-1-default
10966 verbose argv "/usr/bin/node10" "/usr/bin/npm-default" "-g" "i" "8eecf0d2/netlify-local"
10967 verbose node v10.13.0
10968 verbose npm v6.4.1
10969 error path /usr/local/lib/node_modules/netlify-local/.dist/cli.js
10970 error code ENOENT
10971 error errno -2
10972 error syscall chmod
10973 error enoent ENOENT: no such file or directory, chmod '/usr/local/lib/node_modules/netlify-local/.dist/cli.js'
10974 error enoent This is related to npm not being able to find a file.
10975 verbose exit [ -2, true ]
Should handle use case where the webpack config is an array of configs, probably common for small applications where the client and lambda's are in the same repo.
/webpack.config.js
const lambdaConfig = require("./src/lambda/webpack.config.js");
const clientConfig = require("./src/client/webpack.config.js");
module.exports = [
lambdaConfig,
clientConfig,
]
In addition to #11, the Netlify configuration could also be used for other netlify-local options.
[plugins.local.webpack]
config = "webpack.js"
[plugins.local.server]
static = true
lambda = true
certificates = "private/certs"
port = 9000
[plugins.local.functions]
source = "src/lambda/ts"
files = [
"foo.js",
"nested/bar.js"
]
This isn't as pretty as I'd like but I'm new to toml so maybe there's a better way to write this
[netlify-local] starting http server
events.js:183
throw er; // Unhandled 'error' event
^
Error: listen EADDRINUSE :::8100
at Server.setupListenHandle [as _listen2] (net.js:1360:14)
at listenInCluster (net.js:1401:12)
at Server.listen (net.js:1485:7)
It is fairly common to be running multiple instances of an app framework in development, with ports preselected by a tool such as netlify-local .
ionic service
looks for the next available port, and iirc ng serve
does the same.
netlify.toml
has the build
command .. it just needs to be run, .. on unix ;-)
For windows, a workaround would be to do the build using docker with the netlify build image.
That would even be useful in some instances for unix users.
Since the different Netlify Services aren't completely defined, testing will be based on current assumptions about how things should work. In addition to writing tests, adding more error handlers should be considered (eg, invalid webpack config).
parseWebpackConfig()
parseNetlifyConfig()
Webpack.initialize()
Webpack.watch()
Webpack.build()
Server.initialize()
Server.listen()
Server.close()
Server.routeRedirects()
Server.routeHeaders()
Server.routeLambdas()
Server.lambdaRequest()
Server.lambdaContext()
Although this is out of the original scope for netlify-local I've been thinking a bit about the best way to implement this..
I think it's critically important to ensure end users can supply their own Webpack configurations and for netlify-local to be very cautious and explicit with any modifications it makes.
An example of the bundle command would require you to specify the Netlify and Webpack configuration files.
netlify-local bundle -n netlify.toml -w webpack.config.js
This would work in very much the same way that the serve
command already does, however we need to add some logic to figure out what files are going to be used as Netlify Functions, a neat idea which I'm semi-skeptical about employing is to modify the Netlify configuration with a plugins
property 🤭
Once we have a list of functions, we still need to modify the Webpack configuration - using 8eecf0d2/webpack-netlify-lambda-plugin seems like a good solution.
From there the user could define options within their Netlify configuration which will be used by 8eecf0d2/webpack-netlify-lambda-plugin.
[build]
...
[plugins]
[local]
source = "src/ts"
functions = [
"foo.js",
"nested/bar.js"
]
I'm sorta surprised Netlify doesn't require you to specify which files are Functions but considering there's no real options for individual Functions it makes a little bit of sense.
I'd like to see Netlify support options similar to what you get with Serverless configurations (or the other way round and see Serverless support Netlify as a provider!)...
[[functions]]
name = "foo"
file = "functions/foo"
method = "GET"
...
Modifying the schema of Netlify configuration scares me a little since they might not have thought about such a use case and even if they have it might not align with their plans for the future.
Probably a lot of gotchas with Netlify Functions but implementing what's stated in docs should be simple enough.
Documentation: https://www.netlify.com/docs/functions#the-handler-method
context
arg.🚨 You need to enable Continuous Integration on all branches of this repository. 🚨
To enable Greenkeeper, you need to make sure that a commit status is reported on all branches. This is required by Greenkeeper because it uses your CI build statuses to figure out when to notify you about breaking changes.
Since we didn’t receive a CI status on the greenkeeper/initial
branch, it’s possible that you don’t have CI set up yet. We recommend using Travis CI, but Greenkeeper will work with every other CI service as well.
If you have already set up a CI for this repository, you might need to check how it’s configured. Make sure it is set to run on all new branches. If you don’t want it to run on absolutely every branch, you can whitelist branches starting with greenkeeper/
.
Once you have installed and configured CI on this repository correctly, you’ll need to re-trigger Greenkeeper’s initial pull request. To do this, please delete the greenkeeper/initial
branch in this repository, and then remove and re-add this repository to the Greenkeeper App’s white list on Github. You'll find this list on your repo or organization’s settings page, under Installed GitHub Apps.
pnpm is a wonderful replacement for npm, but it isnt working with netlify-local
.
pnpm -g i netlify-local
Resolving: total 269, reused 205, downloaded 00 0wnloaded 0
Packages: +1
++-
Resolving: total 379, reused 377, downloaded 2, done
/home/jayvdb/vs/node/8.13.0/pnpm-global/1:
+ netlify-local 1.6.0
jayvdb@linux-lwww:~/projects/viperdev/template/ionic> netlify-local serve
module.js:550
throw err;
^
Error: Cannot find module 'serve-static'
at Function.Module._resolveFilename (module.js:548:15)
at Function.Module._load (module.js:475:25)
at Module.require (module.js:597:17)
at require (internal/module.js:11:18)
at Object.<anonymous> (/home/jayvdb/vs/node/8.13.0/pnpm-global/1/node_modules/.registry.npmjs.org/netlify-local/1.6.0/node_modules/netlify-local/.dist/server.js:52:19)
at Module._compile (module.js:653:30)
at Object.Module._extensions..js (module.js:664:10)
at Module.load (module.js:566:32)
at tryModuleLoad (module.js:506:12)
at Function.Module._load (module.js:498:3)
After a little patch, and a little fiddle,
> pnpm run test
> [email protected] pretest /home/jayvdb/projects/netlify/netlify-local
> pnpm run build
> [email protected] build /home/jayvdb/projects/netlify/netlify-local
> tsc --project ./tsconfig.json
> [email protected] test /home/jayvdb/projects/netlify/netlify-local
> ts-mocha --project ./test/tsconfig.json test/**/*.ts
Config
parseNetlifyConfig
✓ should throw when not found
✓ should correctly parse build
✓ should correctly override build with context
parseWebpackConfig
✓ should throw when not found
✓ should correctly import webpack config
Server
lifecycle
✓ should listen and close
✓ should add redirect routes
✓ should add redirect header routes
✓ should add header routes
✓ should add lambda route
✓ should correctly format lambda request
✓ should correctly format lambda context
12 passing (202ms)
Would be handy to expose an API so test runners can start & stop the server, optionally with the build system.
import { parseNetlifyConfig, parseWebpackConfig, Server, Webpack } from "netlify-local";
const netlifyConfig = parseNetlifyConfig("netlify.toml");
const port = 3000;
const server = new Server({
netlifyConfig: netlifyConfig,
routes: {
static: true,
lambda: true,
},
certificates: {
key: <private key as a string>,
cert: <certificate as a string>,
},
port: 9000,
});
await server.listen();
await server.close();
const webpackConfig = parseWebpackConfig("webpack.config.js");
const webpack = new Webpack(webpackConfig);
await webpack.build();
webpack.watch();
parseNetlifyConfig()
parseWebpackConfig()
constructor
Server.listen()
Server.close()
constructor
Webpack.build()
Webpack.watch()
Would be cool to integrate Github Actions and drop Travis dependency - have just tried to implement with little success and could not filter by tag or figure out how to only yarn publish
based on tag.
Not really interested in testing this so PR appreciated.
develop
, feature/*
and hotfix/*
branchesyarn install
yarn test
master
branchbranch = master, tag = *.*.*
yarn install
yarn test
yarn publish
Netlify doesn't clearly specify required properties for toml
configs and testing what happens within different scenarios is a pain so for the purpose of simplifying things I think it's best to enforce explicit with toml
configurations, for example an error will be thrown if the static router is being initialised but there is no build.publish
property specified.
-c --context
option to override.base
prop.from
, to
prop.status
prop.force
prop (could be tricky).query
prop (could be tricky).conditions
prop (could be really tricky).headers
prop.for
prop.Currently there is a backtrace if build.functions
doesnt exist in the toml file.
That should disable the lambda , allowing basic static site serving without cli extra flags.
Would be nice to add support for HTTPS, probably keep it simple and just pass in a directory and expect key.pem
, cert.pem
to exist.
netlify-local serve --certificates private/certs
10.12.8
to 10.12.9
.This version is covered by your current version range and after updating it in your project the build failed.
@types/node is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.
There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.
Your Greenkeeper Bot 🌴
I've not dug into this problem, so I dont know the exact cause.
[netlify-local] TypeError: Cannot read property 'length' of undefined
at pathtoRegexp (/home/jayvdb/vs/node/8.13.0/lib/node_modules/netlify-local/node_modules/path-to-regexp/index.js:67:49)
at new Layer (/home/jayvdb/vs/node/8.13.0/lib/node_modules/netlify-local/node_modules/express/lib/router/layer.js:45:17)
at Function.use (/home/jayvdb/vs/node/8.13.0/lib/node_modules/netlify-local/node_modules/express/lib/router/index.js:464:17)
at Function.<anonymous> (/home/jayvdb/vs/node/8.13.0/lib/node_modules/netlify-local/node_modules/express/lib/application.js:220:21)
at Array.forEach (<anonymous>)
at Function.use (/home/jayvdb/vs/node/8.13.0/lib/node_modules/netlify-local/node_modules/express/lib/application.js:217:7)
at Server.routeStatic (/home/jayvdb/vs/node/8.13.0/lib/node_modules/netlify-local/.dist/server.js:95:22)
at Server.initialize (/home/jayvdb/vs/node/8.13.0/lib/node_modules/netlify-local/.dist/server.js:82:14)
at new Server (/home/jayvdb/vs/node/8.13.0/lib/node_modules/netlify-local/.dist/server.js:66:14)
at Object.<anonymous> (/home/jayvdb/vs/node/8.13.0/lib/node_modules/netlify-local/.dist/cli.js:80:30)
netlify.toml:
[build]
command = 'export PATH=./.ci/bin/:"$PATH" && build-netlify'
publish = 'www'
[[redirects]]
from = '/api/*'
to = 'http://localhost:8000/:splat'
status = 200
force = true
[[redirects]]
from = '/*'
to = '/index.html'
status = 200
I can work around this by editing /home/jayvdb/vs/node/8.13.0/lib/node_modules/netlify-local/node_modules/path-to-regexp/index.js function pathtoRegexp
to add
if (path === undefined) {
return new RegExp();
}
The site seems rather ok, with that hack, but ive not exhaustively tested yet
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.