Wednesday, September 20, 2017

Bookmark: Offline-only content

I may consider doing something like this for the BMapp: Offline-only content.

https://chris.bolin.co/offline/

Friday, September 15, 2017

Bookmark: The Jupyter Notebook

The Jupyter Notebook is an open-source web application that allows you to create and share documents that contain live code, equations, visualizations and explanatory text. Uses include: data cleaning and transformation, numerical simulation, statistical modeling, machine learning and much more.

http://jupyter.org/

Thursday, September 14, 2017

Bookmark: Web Workers

Web Workers makes it possible to run a script operation in background thread separate from the main execution thread of a web application. The advantage of this is that laborious processing can be performed in a separate thread, allowing the main (usually the UI) thread to run without being blocked/slowed down.

https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API

Baby perspective on adults

Adults probably seem kind of like monsters to small children. Besides the obvious things, like that we are large and talk in loud, deep voices; we also do weird, dangerous things in the kitchen like boil water and cook food, which we then eat as hot as we can handle it. Hot coffee, hot soup, food with molten cheese toppings and such probably seem like monster food to babies; which we gobble up with huge bites.

But for that matter, babies seem like weird little creatures to older children. Especially newborns who can't do much except cry and just lie there like blobs. Adults are always boiling their bottles, wrapping them delicately in sterilized fabrics and such. And they smell bad quite often.

Like adults, really, if we're being honest.

Wednesday, September 13, 2017

Configuring Typescript in Visual Studio 2017

Be aware that there are 2 places to configure Typescript behavior in Visual Studio 2017 (and older, I assume).  They do not communicate with each other.  The first is the tsconfig.json file at the root of your project (the one you get when you type tsc --init in the command line).  The second is in the properties of your project (right-click the project folder in Solution Explorer => Properties => Typescript Build).

If you find your Typescript behaving in a way that is different from what you expect, make sure that both config files are synced.

For instance, despite my explicitly putting'compileOnSave':false in tsconfig.json,  javascript files kept popping in next to my .ts files at every save.  It was because Compile on save was checked in the project properties.


The More You Know!

Tuesday, September 12, 2017

Bookmark: Fake data

Fake Online REST API for Testing and Prototyping
http://jsonplaceholder.typicode.com/

Quick & simple image placeholders.
https://placeholder.com/

Bookmark: Stack Share

Discover & discuss the best open source and SaaS tools
  • Discover new tools and services 
  • See side-by-side comparisons 
  • Share your tech stack 
https://stackshare.io/

Monday, September 11, 2017

Bookmark: Tech Conferences Calendar

I'm maintaining a calendar of tech conferences and conventions around the world, mainly programming related. I add them as I become aware of them. If something is missing, here, or you'd like to help maintain it, shoot me an email. Here are public links: HTML and iCal format.

Bookmark: CSS Methodologies

Here are various methodologies for structuring CSS:

OOCSS (Object Oriented CSS)
SMACSS (Scalable and Modular Architecture for CSS)
BEM (Block Element Modifier)
SUIT CSS (Style tools for UI components)
Atomic CSS
ITCSS (Inverted Triangle CSS)
Enduring CSS

Stylable is a pre-processor and component library that also has structuring constraints.

More will be added as discovered.

Here is a danger to be aware of.
Third Party CSS Is Not Safe

Sunday, September 10, 2017

Bookmark: DEC64.com



DEC64 is a number type. It can precisely represent decimal fractions with 16 decimal places, which makes it very well suited to all applications that are concerned with money. It can represent values as gargantuan as 3.6028797018963967E+143 or as measly as 1.0E-127, which makes it well suited to most scientific applications. It can provide very fast performance on integer values, eliminating the need for a separate int type and avoiding the terrible errors than can result from int truncation.

http://dec64.com/



Friday, September 8, 2017

CDNs vs. bundling

Remember, this is a personal sketchbook, not a how-to guide nor really even a blog.  So I might have some bad ideas on here.  Might even be terrible.  That's ok.

I created cdnler to help me with a workflow of using Typescript, but without necessarily loading modules through npm.  If I were to use Ramda to build a site, I would load (only) Ramda's type declarations using npm, so that its classes and methods would be available to my development environment.  But on the web page itself, I'd just use a script call to a CDN.  Any project I'm working on might have 5 or 6 CDN calls on one page, and since it's best practice to use CDNs only with a local fallback, for production I'd have to download every CDN asset file by hand, and then hand-code its fallback. cdnler just does that.

Which is fine as far as that goes, but the fad these days, backed by the power of Google, is to bundle up all of your javascript into a single, or two, large, minimized files, and then link to those from within your page. This has the advantage of reducing server calls, since a script reference blocks any other browser activity until that call is resolved.  CDNs are another way of handling this bandwidth issue, since in theory, a CDN asset would be cached on the browser, and presumably shared when the same browser visits a different site with that same asset, but, to be honest, that's a bit dubious. Considering, jQuery alone, there are so many different versions, and so many different CDNs that host it, that even sites that use jQuery, and a CDN to reference it, would not necessarily be caching the same files. As well, Google now wants your site to be a progressive app, which makes CDN references problematic.  Not impossible, but the tide is against that method.

The expected way to bundle javascript code is to load of external libraries locally using a package manager like npm or yarn. Then, in the code, to require them using node.js syntax e.g.

import R = require('ramda');
and then to use a build tool like browserify or rollup which work by following all those require calls up the abstract syntax tree to know what libraries comprise the app, mushes them all into one file, which is what then goes into the <script> src reference.

Here's where my bad idea comes in.  Why not build a companion module to cdnler, that would follow all of the local script references in an html file (<script src="local.js">), then bundle and minimize those local assets?  Then it could replace those script references in the html file with a single script reference to the bundled asset. It wouldn't need to do any so-called treeshaking, just put the contents of each file in just a long file of its own.

To recap, this hypothetical work-flow would be to reference external libraries using CDNs during development, and then  download them locally during pre-build, then bundle them into a single (or more) local file during build, and then replace the CDN script references in the html with a single a reference to that local file.

What would be the point?  I just like working with CDNs.  There's something neat about having the world's javascript libraries available to just a single flat index.html. And there's something hegemonically monocultural about using npm to manage all of everyone's code.  If there's ever a problem with npm, we're all in trouble. So, it's a good thing, I think, to have a variety of ways to build and create apps.

Thursday, September 7, 2017

Brunch and BMapp

The "Burning Man App" (I'm settling on the working title BMapp) that I'm building has stalled for a minute. Before I dig in, and move from proof of concept to actual build, I want to make sure that the architecture and pipeline are solid. That is to say, I'd like a good framework and a build task that keeps the coding itself relatively simple. For the framework, I've settled on Inferno, because it is light and fast.  While its key developer has left (?) the project to move onto React at Facebook, and I'm not sure what that means for Inferno's future, for now, the relative advantages yet go to Inferno.

As to a build task, the Inferno team itself appears to recommend Brunch, an open-source, community-driven "build tool" rather than a "generic task runner". Its main selling point is that it reduces some of the monstrous complexity that some build task runners can encompass.  A single brunch-config.js file pointing to input files, plugins and some output directories, and boom, you have a minified, uglified, compressed, tightened, tested web app. No fuss, no muss.  Sounds great!  Also, during setup I ran into a few errors (that were ultimately caused by a flawed npm release, not Brunch): with one issue ticket the Brunch team was incredibly responsive.  They were on it!  Even committing to closing out the issue over the weekend!  That is dedication. "Windows support is very important to us."

So, when I say that Brunch isn't working for me, it is by no means a slight of Brunch itself or the hardworking team that created it. If you're looking for a build pipeline, do check it out! This post is more a documentation that I tried it, and why I'm moving on.

I generally like to code javascript using Typescript, for a number of reasons, but mostly because it is javascript, only with strict typing. Coding with it prevents me from easily relying on type ambiguity (and the advantages that ambiguity can sometimes confer), and in return, I'm made aware in the editor, even before compilation, of potential problems.  Other advantages: I can use the latest and greatest coding practices from ES6 and later (does what Babel does), and my code will automagically be compiled into whatever version necessary.

Brunch kinda has typescript support, but see, that's the thing: it suffers from the same issue that all popular task runners do: you need to rely on some intermediary plugin that may, or may not, be up-to-date. Brunch uses 'skeletons' which are a kind of template or starter pack for different configurations.  Their official 'brunch with typescript' skeleton, out of the box, gives you a `brunch-typescript is unsupported, use typescript-brunch instead` deprecation message.  Okay, no big deal, I'll just swap out the brunch-typescript plugin for the typescript-brunch plugin.  But typescript-brunch has this notation: "From version 1.8.2 up to current version, this plugin may report TypeScript errors that you are not expecting" and "We are hoping to support the full language service, at least for brunch build at some point, but until then...[etc]".  Not exactly inspiring confidence.  Okay, no big deal.  I'll just use Typescript itself to compile to javascript, and once there, let Brunch takeover to do what it does best.

On to uglify js, the minimizer.  I followed all instructions as I understood them to get it working and it just plain did not work, meaning, to minimize and 'mangle' the compiled javascript; or really, to have any effect at all. Simply installing the plugin and referencing it in the config file appeared to have zero effect on the code itself.  No doubt, and I mean this, it's my bad.  I didn't understand the instructions, or didn't fiddle with it enough.  Perhaps if I had changed the order of the plugins, or if I had only spent another 10 minutes or half-an-hour, then I'm certain I could get it working as expected.

And, it's community driven! If it's not working, get on the stick! It's not like you can demand your money back. Write up a ticket describing the issue.  Ask questions on the forum! Write the bug fix, if that's what's necessary. I get it!  But that's the thing:  I had already spent a lot of time with it already.  A task runner / builder / DevOp tool / what-have-you is supposed to make things easier, minimize errors and time in the setup and manipulation of code.  If you're spending as much time on the tool as you would just rolling your own, then it's maybe best to roll your own.  My spare coding time, right now, is dedicated to getting this BMapp up and going.

So, for now, it's back to using npm as my build tool.  It's simple, it works, and if something isn't there, it's super easy to code up a module that does what you want.

Visual Studio 2017 and Frontend Development

Visual Studio 2017 is a great IDE for frontend development that has some extremely picky, opinionated ideas about how you should set up your projects.  And since I, too, have extremely picky, opinionated ideas about how I should set up my projects, too, we often fight during setup, VS2017 and I.  VS2017 is a cranky old man who hired you to mow his lawn, insists that you wear gloves and smeary safety glasses, that you mow out back before you mow out front, and then forgets what he told you and yells at you anyway.  That's only during setup, though.  Once you get going, VS2017 is a dream.

If you, like me, use npm; git; a task runner; have a development folder separate from your production folder; and run a web server from your production folder; even if you're not at this point interested in the backend - or want to use an entirely different IDE and technology than .NET; then you can get the good parts of VS2017 without annoying Scripts folders and what-not.

These are the precise steps to follow to turn that Visual Studio 2017 from an angry old man into a cooing, cuddly baby. An extremely useful baby.

(Oh, by the way, this is if you're setting up a new project.  VS2017 makes you jump through a whole host of other annoying steps if you have already set up another project, so follow these steps only if you have not yet set up you project.  I may, or may not, cover the latter case in another post.)

  1. Open VS2017, then do File => New Project
  2. Choose Blank Node.js Web Application
  3. Fill in the fields in this way:
    •   Name => dev 
    •   Location => the *parent* directory of where you want your project to live. 
        e.g. /workshop/websites 
        (Not inside a folder named for your project. e.g. NOT /workshop/websites/MyProject)
    •   Solution => create new solution
    •   Solution name => *this* is where you put the name of your project's folder.
        e.g. MyProject
    •   Check both create directory for solution and create new git repository.
  4. Click OK.
  5. From the 'Solution Explorer', you can go ahead and delete the Scripts folder, package.json, README.md and server.ts.  
  6. Right click the 'Solution' node in the 'Solution Explorer' and pick 'Add' then 'New Website'
  7. Choose ASP.NET Empty Website.
    Don't worry. There is no ASP.NET involved.
  8. Web location: browse to the project directory (e.g. MyProject) and create a new folder named dist by adding its name to the path in the field named "Folder:"
    e.g. C:\workshop\websites\MyProject\dist
  9. Click 'open'. You should get a dialog box telling you that 'dist' does not exist and asking if you would like to create it. Click 'Yes'.
  10. Click 'ok'.
  11. Click through any warnings.
  12. Go ahead and delete the Bin folder, packages.config and Web.config.
  13. Right-click on the 'dist' node in the 'Solution Explorer' and click 'Add' => 'Add New Item'
  14. In the "Name:" field write 'index.html'
  15. Click 'add'.
  16. In the editor, add a "hello world" message in the <body> tag.
  17. Right click the 'dist' node in the 'Solution Explorer' and select 'View in Browser'.
  18. If you see your index.html message, success!
  19. Right-click the root 'solution' node in the Solution Explorer.
  20. Select 'Add' => 'New Solution Folder'
  21. Name it 'root'.
  22. Right-click, 'Add' => 'Existing Item'.
  23. Select .gitignore and any other relevent file from your project folder (the parent of 'dev' and 'dist', e.g. MyProject).
    Now these are easily accessible in the Solution Explorer from the 'root' folder. Do this any time during development if there are files in there you would like to see inside the 'Solution Explorer'.
  24. Related, if at any time there is a file that is definitely in the dist or dev folder but is not showing up in the Solution Explorer, check for an icon along the top just under the title 'Solution Explorer' named 'Show All Files'. Click that. Your missing file should show up. You can right-click its icon and select 'Include in Project' if you like.
  25. Select View => Other Windows => Terminal Window. (Or use Power Shell or CMD).
  26. In the 'dev' directory type:
    1.   npm init, then fill in the information
    2.   tsc --init => creates a typescript.config file.
    3.   git status => check to see if there are any files that need to be added to .gitignore
  27. If all is well, this would be a good time to type 'git -m "init commit"'
  28. Now the world is your oyster.

Saturday, September 2, 2017

Word distance calculator

A friend on Facebook posted this:

Ruin a book with one letter. First try, Naked Bunch.

Some of the other answers were Night Club, Moby Duck and Sale of Two Cities. I wondered if I could use Uncle Tom's Cabin somehow, but then it occurred to me that it would be fun to have a program that would give all words within n letter distance from some arbitrary word. So, I could enter Cabin and see if there were words within 1 letter distance.  I looked online for about 30 seconds, and didn't find it, so that means that no one has ever thought of that, ever.

So, that's my idea. Code a function where ('tale', 1) returns ['sale', 'male', 'pale', 'talk', 'tall', 'tile', ...etc].

It could be a component of a longer program that calculates answers to those problems like 'Turn pain into rail in the shortest number of steps possible, wherein each step you can change one letter in the word. e.g. pain => rain => rail'

Edit (really, 2 minutes later).  I was looking for the Levenshtein Distance.  I knew that!

Edit. Well, would you look at that:  Levenshtein-Automata

Edit.  And that. Levenshtein-Puzzle

Edit.  Approach would be to find the n=1 distance by inputting the word, say word, and search a dictionary for .ord then w.rd then wo.d then wor. and concatenate the results.  Simple. To find n=2 distance, input each of those words into the same function, but being careful to filter out searches that would search the same space.  And so on. [Edit.  No, that's dumb.  To find n=2, just search a dictionary for ..rd then .o.d then .or. then w..d and so on.]

Edit.  Okay, done.  Also on Github.

I have used it to find these gems:

  • War and Pence
  • A Portrait of the Autist as a Young Man
  • Brave Neg World
  • The Gripes of Wrath
  • The Pun Also Rises
  • The Sub Also Rises
  • Tropic of Canker
  • The Maltose Falcon
  • The Catcher in the Eye
  • Something Wacked This Way Comes
  • Men and the Art of Motorcycle Maintenance
  • The Call of the Mild
  • Nuked Lunch
  • Bridesdead Revisited
  • Sometimes a Great Lotion
  • American Goys
A fun little project.  

Friday, September 1, 2017

Coming along. Framework hesitancy. The Redux Decision.

The Burning Man App is coming along.  What started out as a proof of concept playing with the data has gradually moved towards becoming an actual web app.  The journey of building it has been taking me through some adventures (if we can quite loosely define 'adventure' here as 'source code' and 'articles about code').  (Also, it's to the point that I'm going to have to choose a name, and I don't want to run afoul of copyrights / trademarks.  The Burning Man App is a good working title, but probably not for release.)

A few new things I have learned:

There is a whole ecosystem of virtual DOMs.
There are tons of web application frameworks in active use and development, not just React and the Angulars.
Lighthouse is a thing.
Page Speed Insights is a thing.

Given the nature of the app, I'm probably* going to have to use a framework that supports a virtual DOM.  Page Speed Insights reports that it contains over 3,000 elements (stating that less that 1,500 is desirable).  This is undoubtedly because of the SVG that comprises the Black Rock City map, which, besides the infrastructure of the city itself, also contains icons representing 308 artworks, 1,299 camps, and 3,374 events!

This will necessarily require some optimization though, because, while desktops and fancier smart phones can handle all that, under-powered phones and tablets crawl. The app doesn't really need to display all of the events at once, either.  I can also probably insert icons only as the user zooms in, and only within its viewport.

I'm still not ready to pull the trigger on a full-blown framework, yet.  I'm peering closely at Vue.js, but we'll see.  Not sure why I'm so reluctant to wade into React.  It would be good for my professional development to at least be familiar with it, but as this app is a labor of love, I want any technology to fit with what I want to do, rather than trying to fit the app into some mismatched box.  To those of you who already know a framework, including my future self, it may be hard to understand this hesitancy. But remember: learning a framework takes an investment of time and energy; time and energy spent learning a framework is time and energy not spent developing the app; not spent with family and friends; and, at the end of the day, your app is now married to a community and ecosystem that may or may not be a good match. A divorce is costly. Apps also require maintenance, and if it has been some time since using that framework, and the framework you've chosen badly is unintuitive, then you will have to spend time relearning (on some level, this is my reluctance with React: everything - javascript, HTML and even CSS appears to be jumbled all up together in JSX). There are pros, of course, but those are some of the cons.

I have committed to using Redux, however, at least for the user interface.  Keeping application state in a single object to which all elements refer makes a lot of sense. The app will be able to store that state, as well, so that the user can return to the app as it was.  It will also be much easier to integrate a framework when the time comes.