Gulp, typescript, angular2, webpack for my studying

В общем так сложилось, что несмотря на то, что время от времени необходимо бывает заниматься фронтендом, никак не доходили руки до Angular. Точнее ни до чего серьезней хеловорда.

И пока я использовал jQuery и Module pattern — оказалось, что подоспел уже второй «ангуляр». Ну и наконец-то дошли руки попробовать его не просто так, а попытаться применить на деле. Тем более, что мне пришелся по вкусу Typescript.

И попутно встал вопрос как использовать этих проб. Т.е. нужно чтобы несколько разложенных по package’ам typescript файлов транспились (transpile) в javascript, собирались в один или небольшое(!) количество итоговых ресурсов для подключения в html.

Так как уже не раз использовался в работе Gulp, причем полностью оправдалось время, затраченое на написание тасков, то тут выбор не стоял.

Сложнее было выбрать что делать дальше. Есть несколько компиляторов ts, есть различные сборщики бандлов (bundle).

После нескольких экспериментов, я посчитал что мне будет удобней использовать webpack.
В качестве лоадера для typescript-а был выбран awesome-typescript-loader — мне он показался более лояльным к новичкам.

UPD: На днях вышел релиз Angular2, и поэтому Вот новый пост про настройку т.к. приведенный ниже для одной из бета версий ангуляра.
Since angular 2 release available now – so this is new record about setting all up.

npm package.json

Итак, для начала package.json для npm:

{
  "name": "testang2",
  "version": "0.0.1",
  "private": true,
  "description": "Test Angular2 #2",
  "main": "index.js",
  "scripts": {
    "lite": "lite-server",
    "start": "concurrently \"npm run lite\"",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "shrewmus (contact@shrewmus.name)",
  "license": "ISC",
  "devDependencies": {
    "awesome-typescript-loader": "^2.2.1",
    "bower": "^1.7.9",
    "concurrently": "^2.2.0",
    "gulp": "^3.9.1",
    "gulp-pug": "^3.0.4",
    "gulp-sass": "^2.3.2",
    "gulp-util": "^3.0.7",
    "lite-server": "^2.2.2",
    "path": "^0.12.7",
    "run-sequence": "^1.2.2",
    "typescript": "^2.1.0-dev.20160823",
    "typings": "^1.3.2",
    "webpack": "^1.13.2",
    "webpack-uglify-js-plugin": "^1.1.9"
  },
  "dependencies": {
    "angular2": "^2.0.0-beta.17",
    "es6-shim": "^0.35.0",
    "material-design-lite": "^1.2.0",
    "reflect-metadata": "^0.1.2",
    "rxjs": "^5.0.0-beta.6",
    "zone.js": "^0.6.12"
  }
}

В принципе тут лишний только bower — дань привычке. Пока что все пакеты, которые ставил через него имели возможность установки через npm.

Чтобы во время экспериментов не поднимать полноценный backend используется lite-server, который по-умолчанию поднимается на 3000-м порту (localhost:3000). Lite-server — это сервер только для разарботки, при запуске открывает адрес в браузере и автоматом обновляет при изменениях в html/css/js. Запускается сервер через concurrently чтобы кроме lite-server’а можно было запустить что-то еще.

Обращаю внимание на то, что с некоторого времени npm перестал автоматом подтягивать peer зависимости и сыпет варнингами — «UNMET PEER DEPENDENCY…»

Теперь приходится такие зависимости ставить вручную (npm install), причем (!) при установке нужно ставить именно те версии, которые требуются в варнингах.

Еще одно замечание — версия typescript. Так как это проект для обучения, то я не привязан к стабильной версии typescript, поэтому не долго думая поставил еще не релизную версию

npm install typescript@nex --save-dev

gulpfile.js

Теперь несколько задач в gulpfile.js

var gulp = require('gulp');
var path = require('path');
var webpack = require('webpack');
var gulpUtil = require('gulp-util');
var sass = require('gulp-sass');
var pug = require('gulp-pug');
var runSequence = require('run-sequence');

/*
* используется как флаг — как собирать: минимизировать
* все или оставлять в читабельном виде. 
* ----------------
* This variable is flag — what kind of compile to use: 
* minimize all or bundle only and stay code in 
* human readable format.
*/
var compType = 'dev';

var filesFilters = {
    allScss: '**/*.scss',
    allPug: '**/*.jade'
};

var paths = {
    app:{
        src:'./src',
        result:'./app'
    },
    sass:{
        src:'./src/scss',
        result:'./assets/css'
    },
    pug:{
        src:'./src/templates',
        result:'./app/templates'
    }
};

/*
* базовый конфиг для вебпака. 
* Base webpack config
*/
var webpackConfig = {
    debug: true,
    resolve: {
/*
* добавлена возможность работать с typescript и 
* html — хочу поэкспериментировать и часть шаблонов
* собрать внутрь *.bundle.js. 
* ---------------------
* Add typescript and html file to use with webpack — in 
* future I want make experiment and insert some of 
* template inside *.bundle.js file
*/
        extensions: ['', '.webpack.js', '.web.js', '.ts', '.tsx', '.js', '.html']
    },
    module: {
        loaders: [
            {test: /\.ts(x?)$/, loader: 'awesome-typescript-loader'},
            {test: /\.html$/, loader: 'raw-loader'}
        ]
    },
    output: {
        filename: '[name].bundle.js'
    }
};


gulp.task('app.webpack',function () {
    var config = {};
/*
* делаю копию конфига вебпака — возможно исходный 
* конфиг понадобится для новых задач. 
* --------------
* I make copy of webpack config into new 
* variable: maybe base config will be used in new tasks
*/
    Object.assign(config, webpackConfig);
    config.output.path = path.join(paths.app.result);
/*
* boot.ts — точка входа. 
* В этом файле загружается angular2 приложение. 
* ---------------
* boot.ts - this file is entry point 
* of my studying Angular application
*/
    config.entry = {
        'app':path.join(__dirname, paths.app.src, 'boot.ts')
    };
/*
* для сжатия используется uglifyjs плагин для вебпака. 
* For minimization used webpack plugin — uglifyjsplugin
*/
    if(compType == 'min'){
        config.plugins = [
            new webpack.optimize.UglifyJsPlugin({
                sourceMap: false,
                mangle: false
            })
        ];
    }

/*
* Собственно запуск вебпака в работу. 
* Run webpack action
*/
    webpack(config,function (err, stats) {
        if(err){
            throw new gulpUtil.PluginError("webpack", err);
        }
        gulpUtil.log("[webpack]",stats.toString({}));
    });
});

/*
* сборка scss файлов. 
* Compile scss to css
*/
gulp.task('scss.compile', function () {
    var outputStyle = (compType == 'min') ? 'compressed' : 'nested';
    gulp.src(path.join(paths.sass.src,filesFilters.allScss))
        .pipe(sass({
            outputStyle: outputStyle
        }).on('error',sass.logError))
        .pipe(gulp.dest(paths.sass.result));
});

/* 
* компиляция pug шаблонов (Pug - бывший jade). Обратить 
* внимание нужно на то, что в качестве конфиг-параметра 
* используется doctype:html. Этот параметр используется
* для того, чтобы корректно обрабатывать большинство
* конструкций синтаксиса angular вроде фигурных скобок
* в атрибутах html тега. 
* ------------------
* Compile pug templates to html 
* (pug — formerly known as jade).
* Note that call to pug used with doctype parameter. 
* This parameter used for correct parse most of 
* angular 2 syntax in template. 
* For example — use braces with html element attributes
*/
gulp.task('pug.build.templates', function () {
    gulp.src(path.join(__dirname, paths.pug.src, filesFilters.allPug))
        .pipe(pug({doctype: 'html'}))
        .pipe(gulp.dest(path.join(__dirname, paths.pug.result)));
});


gulp.task('app.webpack.dev',function () {
    compType = 'dev';
    runSequence('app.webpack');
});
gulp.task('app.webpack.min',function () {
    compType = 'min';
    runSequence('app.webpack');
});

Продолжение следует

Leave a Reply

Your email address will not be published. Required fields are marked *