JavaScript build workflow

Lessons learned

Piotr Lewandowski

@constjs

npm install
npm install -g bower
bower install
npm install -g grunt
grunt

setup flow

./gradlew run

# just works
# no need to install anything

npm

gradle

do we need global dependencies?

use npm scripts

{
  "scripts": {
    "postinstall": "bower install",
    "start": "grunt",
    "release": "grunt build --release"
  }
}

+ more control on remote env
    e.g. Jenkins
 

+ all packages can be local

> npm install
> npm start

> npm run release

no more global dependencies

do we need bower?

+ flat directory tree

+ simple dependency resolution

   (simple yet effective)

+ no big problems actually

- the same work as npm

- additional tool in stack

   (needs to be learnt)

- no clear future

nope. not yet.

still missing some front-end packages*

can I switch to npm?

* you can put direct link to GitHub repo

but that's not the point

npm goals for 2016

better support for front-end flow

  1. Treat git dependencies like registry dependencies.
  2. Front-end asset installer.
  3. Support the new ECMAScript module system.

Don't install libraries

with

10 lines of code!

npm + Jenkins = ?

build = 200MB and 25k files*
         

  • Cache problems
  • Quota
  • Limit of inodes
  • Internet connection

*backend and other stuff per job = ~1GB

npm install
--no-optional
--cache-min=999999
--quiet

npm + Jenkins = ❤️

npm 3 is slightly better

  • less files
  • less space

npm 2+

npm-cache

even better for CI / Jenkins

npm install -g npm-cache

npm-cache install npm bower
  1. calc checksum of package.json
  2. make tarball of installed deps
  3. downloads deps only when package.json will change

build

we use Grunt

1000+ lines of config file

  • a bit messy

  • ... not only in config file

  • ... regular changes needed

clean config

an unexpected journey

single responsibility

one reason to change a file

 

 

separate

  • list of libraries
  • list of modules
  • encapsulated tasks
    • linters

    • optimizations

    • releases

instead of...

dashboard: {
    files: {
        'dist/js/dashboard.min.js': [
            'src/modules/dashboard/module.js',
            '!src/modules/dashboard/route.js'
            'src/modules/dashboard/**/*.js'
    ]
}

// ... repeat for 40 other modules

// ... add new tasks at the end of file

create project abstraction

  
  var APP_MODULES = [
    { module: 'modules.shop',      dir: 'shop',      outFile: 'shop.min.js' },
    { module: 'modules.dashboard', dir: 'dashboard', outFile: 'dashboard.min.js' },
    { module: 'modules.account',   dir: 'account',   outFile: 'account.min.js' }
  ];

make project files structure RegEx friendly

envoriment variables



  var properties = {
      VERSION: version,
      API: '/* @echo API */',
      TYPE: '/* @echo TYPE */',
      REVISION: '/* @echo REVISION */',
      DATE: '/* @echo DATE */'
  };
  • one file!

  • can be injected anywhere

  • can be unit tested

  • list of all possibilities
    in one place

the same rules as clean code

Gandalf approves

Gulp > Grunt


gulp.task("compile", ["tslint"], () => {
    return gulp.src("src/**/*.ts")
        .pipe(sourcemaps.init())
        .pipe(tsc(tsProject)).js
        .pipe(ngAnnotate())
        .pipe(sourcemaps.write("."))
        .pipe(gulp.dest("build"));
});

for more complex apps

+ simple API

+ code over configuration

+ easily separated for many    files

separated front-end?

... you're gonna have a bad time

+ less team communication required

+ easier setup for front-end devs

- synchronization problem

- security

single page app
=

 different security

serve resources from back-end

if your app is the only client
of your API

End Of File

Thanks

JavaScript build workflow

By Piotr Lewandowski

JavaScript build workflow

Lessons learned form JavaScript build process in big project, developed for 1.5+ years. Jenkins tips included.

  • 1,214