Monday, December 14, 2015

How-to: develop a node module - part 2

In part 1 I briefly introduced how to get started with npm and making a module. I recommend that you check that out first if you haven't already.

So, in the previous post I didn't really make a proper module, and it completely lacked structure and relevance to a real world situation. In this post I'll show how I decided to set up my own module and touch lightly on some alternatives along the way. The next, and probably the last in this "series" will be about  testing and setting up a test environment for your npm module. So stay tuned for that.

First off, and with the risk of stating the obvious, but any who: You're not making an application. This means that there is no (graphical)interface, webpack and hot loading is useless, you can't test your module by running it in the browser and therefore there is no need to bundle all your source code and its dependencies into a single bundle etc. When making a module one does not want bloat the source code with an application as well, because when the module is published, we want it to contain only the relevant code and we want it to be as slick as possible.

Two things about project structure

Example / demo

So how do we develop something that we can't really test while we develop it and keep the repository clean and neat at the same time? I wrote that we don't want an application bloating down our repository, this might not always be completely true. A good way to show off a module might be to show our potential users a demo application or examples of how to use it. This is quite common and as long as the example or demo is completely separated from the module code, my opinion is: go for it! Other might disagree. You can develop an example application outside of the repository too in order to completely separate it from your repository.

Source code and distribution code

Just like when developing an application, a good practice is to keep the source code of the module in its own folder. The source code is not the code we publish to npm for others to use, this should be "built" just like when developing a regular app and it's bundled. The built code should not be bundled with its dependencies like webpack and babelify does it normally. The built code should just be transpiled versions of the source code. This allows you to code the module in any javascript version/language you like(regular, ES2015, TypeScript etc), and the users of your module can use any version of javascript they like because your published code is pure(tranpiled) javascript and your dependencies will be installed from your package.json.

Folder structure

Here is an example of what the structure could look like:

├── demo
├── dist
├── src
│   ├── components
│   │   ├── comp.js
│   │   └── class.js
├── models
│   │   └── class.js
│   ├── helpers
│   │   └── class.js
│   └── index.js
├── .babelrc
├── .gitignore
├── .npmignore
└── package.json

demo folder

In the demo folder a small example app can be made that uses the module, this is nice for people who want to see how it is used. Make sure the demo app does not use the code from the source folder.

dist folder

The dist folder is where the transpiled built version will be. This is the version we should publish to npm and this is the version the demo app should use. Some project call this folder "libs", this is a more common name if your module is a set of classes that can be used individually. Just like with React you can Import/require its "createClass" function with:
import {createClass} from 'react';


src folder

In src the source code is kept as per usual. Notice that there is a file called index.js, this is the "main" file of the module(you can name it what ever you want, look at part 1 where this is explained). When other use the module, this is the code that will be imported or required in their scripts. Other than that just structure your source code as you please.

package.json

{
  "name": "asd-nav",
  "main": "dist/index.js",
  //...
  "devDependencies": {
    "babel-cli": "^6.2.0", 
    "babel-preset-es2015": "^6.1.18",
    "babel-preset-react": "^6.1.18",
    "babelify": "^7.2.0",
    "browserify": "^12.0.1"
  },
  //...
  "scripts": {
    "demo": "browserify -t [ babelify ] demo/src/app.jsx -o demo/bundle.js",
    "build": "babel src --out-dir dist"
  }
}

As seen in this package.json, the "main" points to where the built version of my module will be, this is for npm to know what the entry file is when using the module. In this guide I use babel to transpile the source code into the folder "dist" seen by the build script.

The other script called demo, uses babelify(could use webpack or what ever you prefer) to bundle the demo application.

Note that all these are in the devDependencies! Make sure things that are only used in development are in the regular dependencies.

.babelrc

I use a .bablerc file to determine what transpilers to use.

{
  "presets": [
     "react",
     "es2015"
  ]
}

.gitignore

In the git ignore, there is nothing special when using a structure like this. If however you're not using a demo application that in turn is using the built version in the dist folder. It might be a good idea to add the dist folder to the gitignore. Because there is no need to have the built version in your repository.

.npmignore

This works like the gitignore, but its only for when publishing the module to npm. The source code should not be published to npm also the demo should not be there. The only folder that you want published to npm is more or less the dist folder.

demo
src
.gitignore
.babelrc
*.log

Npm ignores some things by default, node_modules-folder for example so they don't need to be added. read more here.

That's it! Your repository is now set up for module development.

Don't forget to build your source code before bundeling your demo and that the demo application should use the built modulenot the source code!
import MyModule from './../dist/index.js';

Thursday, December 10, 2015

Warning: Testing React Stateless Components

TL;DR;
Doesn't work right now(React 0.14)

After a long(long long long) time of trying to set up a test environment for my project that was built with stateless components, I had to give up that thought and accept defeat. Because it seems that it is not possible with the current version of React Test Utils.

What is a stateless component

(aka Stateless Functional Components) They are just what it sounds like, it a component that does not use the state at all. It comes with some nice syntax that allows one to write less code because they consist of only one function, the render function. Therefore also doesn't have to extend from "React.Component" or be created with "React.createComponent"-function.

Here's a small example:
var Hello = (props) => {
    return <h1>Hello {props.name}</h1>;
};
<hello name="Anakin"/>

Kinda sweet huh? 

Why would one want to test something so small and simple that only renders some DOM?

It might seem unnecessary to test something like this, but even in the small example above things can go wrong. What happens if we do not supply a name attribute to the Hello-"component"? Well it will render a h1-tag with no name, that seems like something we would want to test, and maybe refactor in the future. An empty h1 is kind of useless and maybe should not be rendered at all? Maybe a default text should be used if the title is empty or not supplied thought the title-attribute.

Here's the keyword "functional". The components are stateless functional components, they can and most likely will have logic in them. A stateless component with no functionality is essentially just a tag and maybe that should not even be a component at all.

Why is this a problem when testing? 

React has a suite of test tools called "React Test Utils", these have tons of uses, one of them is to "fake render" a component so we can inspect it and make sure it behaves as we expect it to. The test util for this is called "renderer" which renders the component in "shadow-DOM" that allows us to inspect it. When trying to use the renderer with a stateless component it will throw an error saying that the argument(the stateless component) is of the wrong type.

There are some issues on github ragarding this. Some people claim they have found work-arounds most of them seems to be about making a wrapper class for stateless components. Personally this feels like the wrong approach and I will take a step back to revert my stateless components to regular ones extending React.Component and await v0.15 where this hopefully is fixed.

Thursday, November 26, 2015

How-to: develop a node module - part 1

In this course we've learned from day one, how to install node modules and use them in an app. A subject that might be of interest that this course does not bring up is, how does a node module work and how does one go on making one?

A node module is not really different from any component och "class" you make in an regular app. More or less any part of isolated code could be turned into a node module. What might slip one's mind is that whenever the require or import(depending on javascript version) is used, a module is imported for usage. A local one made by one self or a node module made by someone else there is not a big difference in how they're used or accessed.

So let's make a node_module!

I will presume the readers are familiar with git and starting new projects, also that node and npm is installed on the system. Therefore some of the following instructions are not in detail.
Also this will be written in classic javascript style(no TypeScript or ES2015), not that it makes a huge difference but still, now I've said it.
So now then:

In order to do this first step is to register an account at npmjs.com. The account is required for you to publish the module and making it available for everyone through "npm install"-command or the "package.json"-file.

Create a new git repository, I named mine npm-module-test for the sake of this article. Check the box for a readme-file if you want one. Then select "Node" from the gitignore-list at the bottom, this will just fill your gitignore-file with some standard ignore paths common for node projects.

Next, clone the repo to your work-environment and through the terminal/console(will call it terminal from now on) go to the folder where the repo was cloned. Now we can get started.

In the terminal simply type the command:
npm init

There will be a few questions to answer here about the project: its name, version, author etc. There are default settings here so one could complete this step by just pressing return through the entire setup. This will create a package.json-file with the information supplied in the setup. This file can of course be edited so nothing in there is final.

Take a look at the package.json file, there are two important fields in there. The first one is "name", this is the name of your module and this is the name that will be published in npm and used when installing the module. It is a good idea to only use lower case letters and dash to name your module.
For example "my-awsome-module".

The second is the field "main" that will have the value "index.js" if nothing else what chosen during the setup. This one is important because this is the file that will be run when someone uses the module, the entry file, the start file of the module. It's considered a good practice to put the source code in a separate folder from the root, normally named "src" so, create a folder in the root named "src", in that folder create a file named index.js. Now, in the config.json, change the value of "main" to:
{
    ...
    "main": "src/index.js"
    ...
}
Now we've redirect the entry point of the module to a more suitable location.

In this guide the module wont do anything useful at all, because that is not what it is about. So let's add some useless code to the module!

var UselessThing = function(){
    console.log('I am not that useful');
};
module.exports = UselessThing;

Save it and out module is done!

Now lets publish it on npm.
First we have to login to npm in the console using the command:
npm login

You will be asked to enter your username, password and then email

Using this command you can check your local settings to ensure your credentials was stored:
npm config ls

Now run this command to publish the module to npm:
npm publish

And it's done!
Well done! Your useless module is now public on npm and can be used by anyone! To take a look at it go to: http://npmjs.com/package/<package>
where <package> is the name of the module.

If you for any reason would want the code it's here:
https://github.com/afrxx09/npm-module-test
And the published version of the useless module can be found here:
https://www.npmjs.com/package/npm-useless-module-test

it can be installed by running:
npm install npm-useless-module-test

or added to your package json
"dependencies": {
    "npm-useless-module-test": "^1.0.0"
}

Friday, November 20, 2015

Project implementation start

So the project in RIA-development course started this week. As per usual when it comes to projects the hardest part is always figuring out what the H to do. Coming up with a relevant, useful, interesting and meaningful application, that intrigues one to actually accomplish something and to learn instead of just turning in something mediocre that is sufficient to pass the course. This is becomes even more difficult when trying out a new language where one does not have a clue of best practices, structures, tools and development processes.

Now then, some self pity is out of the way, I managed to come up with an idea that I thought would be pretty useful and solid. Making a navigation component that runs with react router. A component that would allow one to simply include the component into ones app that uses React Router and it would generate and render navigation automatically with React Router Links and everything.

At first the idea was to use a json-config-file where one could write down a spec for the routing AND navigation and the component would do everything. Trying this out with a small example app I realized that actually implementing the navigation into apps would be hard. I changed approach to check if My component instead could read all the routes set up by the user and use that to render a navigation. That seems to work much better and it also gives the developer much more freedom when creating their apps.

So there it is, the application I'll be making for this project is a navigation component.

To make it a little more interesting I've started looking into how I can make it into a Node module, because that would be the best way to make is accessible for others to use. Making it as a module makes the process quite different from simply making an application that is running by it self. This weekend or maybe next week, I'll write a blog post explaining the process of developing a module, I need to get a little bit more comfortable and confident my self first.

Friday, November 13, 2015

Mostly idle, but one guild bugfix

I've been pretty idle this week. Got so much done last week where I focused almost entirely on this course, essentially did this weeks work then. My React-Redux-example got some attention, mentioned in two other blogs and cloned 7 times, pretty decent traffic. Hope it has been useful.

David rewrote the code to ES2015 so we created a branch for that so the example now existst in two different styles of javascript. A third version written in TypeScript by Sherief is also on it's way.

Check out Davids ES2015 example code here:
To use it your self, clone the repo
git clone https://github.com/afridlund85/React-Redux-example.git
and change branch:
git checkout -b es2015

A bug in the guild was discoverd. When a member added a Pull Request and that was to a repo that was not by a guild member it caused the guild page to crash when looking at that members profile. Also it could not render Pull Requests properly on the "Deeds" page.

My contribution is in this Pull Request:

Wednesday, November 4, 2015

Simple React Redux example

As a newbie when it comes to Rreact, React Router and React Redux; I found it very hard to get started, even though I have several years of experience in programming. The flow of the applications is hard to follow when using Redux and figuring out how the different parts communicate was not easy. Most tutorials and examples had (in my opinion) too many dependencies  and used a lot of "magic" that did not make sense for a beginner.

I found this fantastic guide that helped me a lot: https://github.com/happypoulp/redux-tutorial.
It describes, in the most minimalistic and simple way; each part of the application flow and the purpose of everything. After reading this and using the example snippets to get redux running(With running I mean without actually doing or rendering anything, but simply not throwing errors in my face), it was much easier to continue.

Using the demo app from the course(https://github.com/krawaller/riastart2015) as inspiration what a "complete" application is. I managed to scrape together a small example where (I hope) there is nothing unnecessary to create confusion.

There are two components called "wrap" and "nav", their purpose is simply to render a container for everything with navigation. Also, there is a "static" component that only renders "Hello world".

The component called "Count" is the tricky one that I tried to make simple. It has two buttons that can increase or decrease a value and it uses redux and the applications state to accomplish this.

Try out the demo:
http://afridlund85.github.io/React-Redux-example/

Check out the code:
https://github.com/afridlund85/React-Redux-example

Monday, November 2, 2015

whois

Hello (world).
I'm Andreas, 30 years old from Växjö. Prior to this education I worked as a webdeveloper, making a CMS with PHP and javascript. When I was sure that programming is what I wanted to do, I took a few years off to get a degree and that is why I'm here.

My main languages that I'm most comfortable with are PHP and javascript, but  many more have been explored and tried in various degrees: C#, C++, ruby and java.

I'm currently using Ubuntu as my OS where sublime is my go-to editor. I like it neat, clean and minimalistic.