How to package your React Component for distribution via NPM

I wrote a React component, transpiling using Babel, bundling and building using Webpack. I wanted to use it in another application via NPM. My NPM publish package needed to include component behavior, styles and images. So how difficult is it to package my React Component for distribution via NPM? An hour or so of work maybe right?

Well, it took me a lot longer to figure this out because of the following speed-bumps.
– React version conflict
– How to bundle and consume styles from a component
– How to include and bundle images

Here are the steps.

1. Make a package npm publishable

npm init

In the package.json, make sure these fields are populated:

package.json
{
    "name": "myUnflappableComponent",
    "version": "0.0.29",
    "main": "dist/index.js",
    "publishConfig": {
       "access": "restricted"
    },
    ...
}

2. Don’t bundle React. Use the parent’s React and react-dom.

  1. In package.json, add React and react-dom in the project’s peerDependencies (And remove it from dependencies, but add it to devDependencies for development)
    {
     ...
     "peerDependencies": {
         "react": ">=15.0.1",
         "react-dom": ">=15.0.1"
     },
     "devDependencies": {
         "react": ">=15.0.1",
         "react-dom": ">=15.0.1"
     },
     ...
    }
    
  2. In your webpack configuration, create a UMD bundle
     ...
     module.exports = {
     ...
     output: {
         path: path.join(__dirname, './dist'),
         filename: 'myUnflappableComponent.js',
         library: libraryName,
         libraryTarget: 'umd',
         publicPath: '/dist/',
         umdNamedDefine: true
     },
     plugins: {...},
     module: {...},
     resolve: {...},
     externals: {...}
    }
    

    And super-duper important, don’t bundle React

     module.exports = {
     output: {...},
     plugins: {...},
     module: {...},
     resolve: {
         alias: {
             'react': path.resolve(__dirname, './node_modules/react') ,
             'react-dom': path.resolve(__dirname, './node_modules/react-dom'),
         }
     },
     externals: {
         // Don't bundle react or react-dom
         react: {
             commonjs: "react",
             commonjs2: "react",
             amd: "React",
             root: "React"
         },
         "react-dom": {
             commonjs: "react-dom",
             commonjs2: "react-dom",
             amd: "ReactDOM",
             root: "ReactDOM"
         }
     }
    }
    

3. Set up your .npmignore file

If you don’t set up a .npmignore file, npm uses your .gitignore file and bad things will happen. An empty .npmignore file is allowed. This is what mine looks like:

    webpack.local.config.js
    webpack.production.config.js
    .eslintrc
    .gitignore

4. Add a ‘prepublish’ script to your package.json

To build before publishing.

"scripts": {
     "prepublish": "rm -rf ./dist && npm run build",
    ...
}

5. Extract out your CSS files for use

We use SCSS files for our styles. These are compiled into css and extracted out by Webpack.

Install the following:

npm install --save-dev extract-text-webpack-plugin node-sass style-loader css-loader sass-loader

Update your webpack.config

const ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = {
    ...
    plugins:[
        new ExtractTextPlugin({
            filename: 'myUnflappableComponent.css',
        }),
    ],
    module:{
        rules:[
            {
                test: /\.*css$/,
                use : ExtractTextPlugin.extract({
                    fallback : 'style-loader',
                    use : [
                        'css-loader',
                        'sass-loader'
                    ]
                })
            },
            ....
        ]
    }
}

6. Images in CSS

The way you include images in your component will determine if the consumer of your component will get them.

I include them in the css file using the content property. For example

.mySky{
    width: 20px;
    height: 20px;
    content: url('../assets/images/thunderSky.png');
}

7. Make sure your images are available outside your component

The issue I ran into was the relative paths of the images in the published CSS files were messed up. After a lot of searching, this article (also in the links below) helped.

Install the following:

npm install --save-dev file-loader url-loader

Update your webpack.config like this:

module.exports = {
    ...
    module: {
        rules: [
            {
                test: /\.(png|svg|jpg|gif)$/,
                use: [
                    {
                        loader: 'url-loader',
                        options:{
                            fallback: "file-loader",
                            name: "[name][md5:hash].[ext]",
                            outputPath: 'assets/',
                            publicPath: '/assets/'
                        }
                    }
                ]
            },
            ...
            resolve: {
                alias:{
                    ...
                    'assets': path.resolve(__dirname, 'assets')
                }
            }
        ]
    }
}

Shoutouts and References:

  1. How to publish your package on npm(all about package.json)

  2. Publish Beta to NPM

  3. Exporting images via webpack (webpack.config.js)

  4. My full webpack configuration:

const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const pkg = require('./package.json');
const path = require('path');

const libraryName= pkg.name;

module.exports = {
    entry: path.join(__dirname, "./src/index.js"),
    output: {
        path: path.join(__dirname, './dist'),
        filename: 'myUnflappableComponent.js',
        library: libraryName,
        libraryTarget: 'umd',
        publicPath: '/dist/',
        umdNamedDefine: true
    },
    plugins: [
        new ExtractTextPlugin({
            filename: 'myUnflappableComponent.css',
        }),
    ],
    node: {
      net: 'empty',
      tls: 'empty',
      dns: 'empty'
    },
    module: {
        rules : [
            {
            test: /\.(png|svg|jpg|gif)$/,
            use: [
                {
                    loader: 'url-loader',
                    options:{
                        fallback: "file-loader",
                        name: "[name][md5:hash].[ext]",
                        outputPath: 'assets/',
                        publicPath: '/assets/'
                    }
                }    
            ]
        },
        {
            test: /\.*css$/,
            use : ExtractTextPlugin.extract({
                fallback : 'style-loader',
                use : [
                    'css-loader',
                    'sass-loader'
                ]
            })
        },
        {
            test: /\.(js|jsx)$/,
            use: ["babel-loader"],
            include: path.resolve(__dirname, "src"),
            exclude: /node_modules/,
        },
        {
            test: /\.(eot|ttf|woff|woff2)$/,
            use: ["file-loader"],
        },
        {
            test: /\.(pdf|doc|zip)$/,
            use: ["file-loader"],
        }]
    },
    resolve: { 
        alias: { 
            'react': path.resolve(__dirname, './node_modules/react') ,
            'react-dom': path.resolve(__dirname, './node_modules/react-dom'),
            'assets': path.resolve(__dirname, 'assets')
        } 
    },
    externals: {
        // Don't bundle react or react-dom
        react: {
            commonjs: "react",
            commonjs2: "react",
            amd: "React",
            root: "React"
        },
        "react-dom": {
            commonjs: "react-dom",
            commonjs2: "react-dom",
            amd: "ReactDOM",
            root: "ReactDOM"
        }
    }
};

Introducing Book-Notes – my notes and highlights from the books I have read

Today I’m releasing Book-Notes – a collection of my notes and highlights from the books I have read.

Screenshot of Book-notes

Reading a book is awesome. Blazing past books at break-neck speed is awesome for only so long. To enjoy the book more, to internalize and chew over what the book has to say, I realized that slowing down and reviewing might be key. So, I started marking out highlights and taking notes when reading inspired by folks like Derek Sivers, Ryan Holiday, Maria Popova (listen at the 31:45 mark) and Tim Ferriss.

This taking notes and highlights is convenient and easy when reading an e-book: on a kindle or the kindle app, or on the Google Play Books app. If I’m reading a paper book, I use the index method: I lightly mark the start and end of the highlight on the page and create an index on the very first page of the book. The index is just a list of page numbers which has these highlights and maybe notes.

I download the Kindle highlights from the Kindle – Your Highlights page using Bookcision. When reading on Play books, it stores the notes on a Google Doc in my Google Drive. Paper books are slower/harder/better/nicer/more-painful. I write down the marked highlights and erase the pencil markings as I go) into my Livescribe book – which gets transcribed and then moved to OneNote.

And now, these notes converted to JSON and will start appearing on the book-notes section of my website.

So, if you are interested in what I’m reading, what I think is thought-provoking in the books I read, come back here regularly to check for new notes and highlights (and some older ones which are being transcribed).

What I used to build book-notes

I used React – using Create React App to build book-notes. It is hosted on my shared hosting space at Webhosting Hub. The code lives in Bitbucket. The design is heavily inspired by Derek Sivers and the Kindle – Your Highlights page. Fonts used: the serif Alegreya for body copy and and the sans-serif Gandhi Sans for headers. Logo is from Flaticon.


VS Code – A tool for writers

Can this be? VS Code – A tool for writers?

Writers use various tools to write. For digital words, we have many options of text editors, word processors and apps. I have used OneNote, Evernote, Google Keep, the WordPress built-in editor, 750 words — in addition to the old-school style of college-rule notebooks, yellow pads and Moleskine journals — for various kinds of writing — blog posts, free form writing, brainstorming or stream-of-consciousness dumping.

However, till now, I had not used a text editor. So why not try to use VS Codethe coding editor I have fallen in love with?

But what exactly are my needs for a writing editor?

  1. A distraction free writing environment
  2. Should count words
  3. Awesome if it can count characters
  4. Spell Checker
  5. Markdown support
  6. Markdown Preview when writing would be so awesome
  7. Auto-save constantly
  8. Lives on the cloud – accessible from all devices

So are these requirements met with VSCode? VS Code – A tool for writers?

Yes!
1. A Zen mode and a Fullscreen mode (this shows the word and character counts).
2. VSCode has plugins for Word counter and character counter and spell checkers.
3. It has beautiful themes (I’m now enjoying the yellow pad looking Solarized Light Theme). I can install fonts (enjoying Hasklig with ligatures).
4. Markdown support and Preview with Auto-Open Markdown (opens in a preview window side-by-side when writing) and Instant Markdown (opens in a new browser) plugins. Even a plugin to convert markdown to pdf, html or text exists.
5. Auto-save – yes.
6. To save on the cloud, I’m going with the nerdy git + bitbucket. And for the truly obsessive, you can sync bitbucket to Google Drive via Zapier.

So yeah, VS Code is really awesome!

So what does VS Code not have, that I miss? Flashy Distracting Features That I still love like from:

  1. OneNote: I love the feature where different text boxes can be moved around like a bunch of stickies on a piece of paper. But admittedly, that is not a distraction-free environment. Great for brainstorming – not so great for distraction-free writing.

  2. 750 Words:
    I love the distraction free environment, the simplicity of the interface.
    I love the badges
    I loved the word counters and the notification when you reach 750 words.
    I love the statistics.
    I love the Seinfeld style – Don’t break the chain strip which counts the days you have shown up to write and met your goal.
    I loved that it use the text-analysis system called the Regressive Imagery Dictionary to calculate the various emotional content of each day’s entry


VS Code Setup Guide 1

In the past few year, I have used Sublime Text as the text editor of my choice for Front End Web Dev work (and to draft these blog posts). I wanted to try a different text editor (FOMO, next cool thing, need more fun … whatever) and decided to try Visual Studio Code or VS Code. This post is my VS Code setup guide.

VS Code is made by the makers of OneNote (which I adore), and it has good reviews from other dev folks. It is also free and has an extensive extensions market. In addition to the installation, in this guide, I list some of the many extensions to improve productivity from the get go and to try to replicate some features I loved in Sublime Text.

Here is the set of links I followed for setup, configuration and customization.

Installation

  1. Installation Link
  2. On Mac only: setup the command prompt for command line invocation.

Customize the Look and Feel

  1. Nomo Dark icon theme: Icons in your explorer window to identify the files types / folders easily.After installing, enable the extension by going to File > Preferences > File Icon Theme > VSCode Icons. (On OSX it is Code > Preferences > File Icon Theme > VSCode Icons.)
  2. Kary Foundation Theme Light theme: I pretty much use light themes. I like the color scheme and the recommended typography. Out of the box, the fonts and text color in this theme isnt’t that great. You absolutely need need to install the recommended Hasklig font, and then it becomes really good.After installing, enable the theme by going to File > Preferences > Color Theme and select “Kary Foundation Theme – Light”
  3. Hasklig Font: A code font by Adobe Systems with monospaced ligatures, recommended for use with the Kary Foundation Theme. After installing the theme on your OS, enable the font. Then go to File > Preferences > Settings and update your settings with the following:
    {  
      "workbench.iconTheme": "vs-nomo-dark", 
      "workbench.colorTheme": "Kary Foundation - Light", 
      "editor.fontFamily": "Hasklig, Menlo, Monaco, 'Courier New', monospace",  "editor.fontWeight": "500", 
      "editor.fontWeight": "normal",
      "editor.fontSize": 15,
      "editor.fontLigatures": true,
      "terminal.integrated.fontFamily": "Hasklig, Menlo, Monaco, 'Courier New', monospace",
      "terminal.integrated.fontLigatures": true
    }  

Set up the editor conveniences

  1. Path Intellisense Visual Studio Code: Plugin that autocompletes filenames.
  2. NPM Intellisense Visual Studio Code: Plugin that autocompletes npm modules in import statements.
  3. Auto Close Tag: Automatically add HTML/XML close tag, same as Visual Studio IDE or Sublime Text does.
  4. Auto Rename Tag: Automatically rename paired HTML/XML tag, same as Visual Studio IDE does.
  5. Expand Selection To Scope: This extension introduces a command that incrementally expands the selection to the nearest outer scope (delimited by bracket pairs).
  6. Paste and Indent: Paste some code with “correct” indentation.
  7. AB HTML Formatter: This tool is formatting / reindenting HTML code.
  8. Rainbow Brackets: Provides rainbow colors for the round brackets, the square brackets and the squiggly brackets.
  9. Guides:Guides is simply an extension that add various indentation guide lines.
  10. Color Highlight: Highlight web colors in your editor.
  11. Color Picker: Helper with GUI to generate color codes such as CSS color notations.

Set up the development conveniences

  1. ES Lint: ESLint Integrates ESLint into VS Code. You need to have installed ESLint first.
    npm install eslint
    
  2. CSS Auto Prefix: Auto-prefixes certain attributes in CSS.
  3. Style Lint: Modern CSS/SCSS/Less linter.Enable the linter, while disabling the built-in CSS and SCSS linter. Go to File > Preferences > Settings and add the following to settings.json:
    { 
      "stylelint.enable": true,
      "css.validate": false, 
      "scss.validate": false 
    }
    
  4. HTML CSS Support: CSS support for HTML documents.
  5. HTML Snippets: Full HTML tags including HTML5 Snippets.
  6. HTML Boilerplate: A basic HTML5 boilerplate snippet generator.
  7. Gulp Snippets: Gulp JS Snippets for Visual Studio Code.

Projects and versioning

  1. Git Extension Pack: Popular Visual Studio Code extensions for Git. Contains the following extensions:
    1. Git History: View git log, file or line History.
    2. Project Manager: Easily switch between projects.
    3. Git Lens: Provides Git CodeLens information (most recent commit, # of authors), on-demand inline blame annotations, status bar blame
      information, file & blame history explorers, and commands to compare changes.
    4. gitignore: Language support for .gitignore files. Lets you pull .gitignore files from the https://github.com/github/gitignore repository.
    5. Open in GitHub / Bitbucket / VisualStudio.com: Jump to a source code line in Github / Bitbucket / VisualStudio.com.

Measuring (for the dataphiles)

  1. Wakatime: Metrics, insights, and time tracking automatically generated from your programming activity.

Debuggers

  1. Debugger for chrome: Debug your JavaScript code in the Chrome browser, or any other target that supports the Chrome Debugger protocol.
  2. Debugger
    for firefox
    : Debug your web application or browser extension in Firefox

Polymer Specific

These extensions are specific to Polymer – a JavaScript library that helps you create custom reusable HTML elements, and use them to build performant, maintainable
apps.

  1. Polymer IDE: Provides linting, autocompletion, and more for web components.
  2. Polymer Syntax: Polymer syntax highlighting for Atom & VS Code!
  3. Polymer Snippets: Sublime snippets for Polymer and Web Components

Additional Settings

These are additional changes to the editor settings to make life easier. Go to File > Preferences > Settings and add the following lines to your settings.json file

  1. Change tab size from 4 spaces (default) to 2 spaces.
    {
      "editor.tabSize": 2
    }
    
  2. Enable word-wrap – if you are crazy like me.
    {
      "editor.wordWrap": "on"
    }
    
  3. Enable the minimap to quickly navigate long files.
    {
      "editor.minimap.enabled": true
    }
    
  4. Show white spaces outside words
    {
      "editor.renderWhitespace": "boundary"
    }
    
  5. Enable formatting on typing and pasting.
    {
      "editor.formatOnType": true,
      "editor.formatOnPaste": true
    }
    
  6. Enable copying the current line when Ctrl+C is pressed without any selection. – Enabled by default!
  7. Enable Files Auto-Save
    {
      "files.autoSave": "afterDelay",
      "files.autoSaveDelay": 8000
    }
    
  8. Enable Polymer to analyze the whole package, though it’s slower:
    {
      "polymer-ide.analyzeWholePackage": true
    }
    

The settings.json file now looks like


// Place your settings in this file to overwrite the default settings
{
    "workbench.iconTheme": "vs-nomo-dark",
    "workbench.colorTheme": "Kary Foundation - Light",
    "editor.fontFamily": "Hasklig, Menlo, Monaco, 'Courier New', monospace",
    "editor.fontWeight": "500",
    "editor.fontSize": 15,
    "editor.fontLigatures": true,
    "terminal.integrated.fontLigatures": true,
    "editor.tabSize": 2,
    "editor.wordWrap": "on",
    "editor.minimap.enabled": true,
    "editor.renderWhitespace": "boundary",
    "editor.formatOnType": true,
    "editor.formatOnPaste": true,
    "terminal.integrated.fontFamily": "Hasklig, Menlo, Monaco, 'Courier New', monospace",
    "stylelint.enable": true,
    "css.validate": false,
    "scss.validate": false,
    "files.autoSave": "afterDelay",
    "files.autoSaveDelay": 8000,
    "polymer-ide.analyzeWholePackage": true
}


February 2017 Reading Log

Here is my reading log from February 2017. Relatively few books but all were quite amazing. And I got to reread my old popcorn favorite series by David Drake – Northworld Trilogy (which seems to be free on Kindle as of today).

If there is one book I would recommend, it would be The Subtle Art of Not Giving a F*ck book cover
The Subtle Art of Not giving a F*ck and The Art of Possibility (yeah.)

Mark Manson’s book is a sometimes-much-needed kick in the pants about what we care about. An excellent read when nearing burnout, dealing with overwhelm or when you just have too much on your plate. You can say that it is a very good time-management book. Ideally, of course, we would apply what he says (and other folks say) and never reach burnout. My favorite part of the book is the Disappointment Panda. He’s awesome. Read it and tell me what you think.

The next on the list: The Art of Possibility book cover The Art of Possibility by Rosamund and Benjamin Zander. I first heard about this book from Seth Godin in his podcast interview with Tim Ferriss. Seth mentioned the set of books he listens to and rereads – again and again – so they can seep into his subconscious. This is one of those audiobooks which I enjoy listening to, and totally get why Seth Godin recommends it. You should try it too.

February 2017 Reading Log

Sunday Monday Tuesday Wednesday Thursday Friday Saturday
1 2 3 4
5 6 7 8 9 10 11
The Subtle Art of Not Giving a F*ck
Mark Manson
(library book
12
It’s Not About the F-Stop
Jay Maisel
(library ebook)
13 14 15 16 17 18
Northworld
David Drake
(ebook)
19
Venegance, Justice
David Drake
(ebook)
20 21 22 23 24 25
26 27
The Art of Possibility
Rosamund & Benjamin Zander
(audiobook CD)
28
The Undoing Project
Michael Lewis
(library book)

You can find all my previous Reading logs here