Привет!





Отгремели фанфары, прошел звон в ушах от истязаний «евангелистов», модников в сфере фронтенд разработки. Кто-то ушел на sprockets, кто-то пустился во все тяжкие и стал писать свои велосипеды или расширять функционал gulp или grunt. Но статей по поводу популярных инструментов автоматизации процесса сборки – стало существенно меньше и это факт! Пора бы заполнить освободившееся пространство чем-то существенно иным.

Уверен многие слышали о webpack. Кто-то подумал «он слишком много на себя берет» и не стал дочитывать даже вводную статью на оффициальном сайте проекта. Некоторые решили попробовать, но столкнувшись с небольшим количеством примеров настройки — отверг инструмент решив подождать пару лет. Но в целом, разговоров «вокруг» ходит масса. В этой статье — хочу развенчать некоторые сомнения. Может быть, кто-то заинтересуется и перейдет на «светлую сторону». Вообщем желающие под кат.



Честно сказать, активно работать с этим мощным инструментом, я начал в начале этого года. Сначала конечно же “wow” эффект. Который достаточно быстро сменился болью от жутко неудобной документации. Но пересилив этот этап – честно забыл о многих типичных проблемах, был поражен скоростью и удобством. Не буду утомлять, разберемся с…

Механика


Логика работы очень простая, но эффективная
Webpack принимает один или несколько файлов, так называемых (entry points) используя пути из конфигурационного файла, далее загружает его.

Сборщик – во время обработки, встречая знакомую ему функцию require() – оборачивает содержимое вызываемого файла в функцию. Которая возвращает его контекст.
При этом не нужно заботиться о «гонке загрузки». Все что вы потребуете, будет доставлено в нужной последовательности!

Важно отметить, что во время разработки, когда запущен webpack-dev-server – промежуточные файлы (chunks) попадают в оперативную память RAM. Браузер же, получает их по протоколу webpack:// прямо из контейнера.
Так же dev-server – поднимает простейший веб сервер на порт 8080, к которому можно достучаться по адресу localhost:8080

Этот подход управления содержимым, как Вы понимаете ускоряет время промежуточной сборки, на значимое количество секунд. Что в рамках рабочего дня – экономит уйму Вашего времени.

Что касается окончательной сборки, то webpack используя тот же конфиг выполняет лишь этап, когда файлы раскладываются по папкам в файловой системе, готовые работать на Ваше благо.

image
source: jlongster.com/Backend-Apps-with-Webpack--Part-III

Подготовка


Тут все достаточно тривиально. Все что нам нужно это node.js и npm. Далее просто следуйте простым командам:

$ mkdir app
$ cd $_ 
$ npm init
& npm i webpack webpack-dev-server --save-dev # важно поставить именно в dev dependencies


Как бы это не звучало, но больше половины Вы уже сделали. Давайте перейдем к конфигурации проекта.
Для этого нужно определить что именно Вы хотите видеть и какие инструменты использовать. Условимся на этом:
  • Common JS
  • Stylus
  • Jade
  • Autoprefixer


Остальное поставим по необходимости.

Настройка



По умолчанию, webpack принимает конфигурационный файл выполненный в формате JSON. Находиться он должен в директории проекта и называться webpack.config.js

Для более удобной работы с запуском задач, а их будет две:
  • Сборка готового проекта
  • Режим разработки

Воспользуемся script секцией package.json файла, добавив следующие строчки:

"scripts": {
  "dev": "NODE_ENV=development webpack-dev-server --progress",
  "build": "NODE_ENV=production webpack --progress"
}


После этого, находясь в директории проекта, Вам будут доступны следующие команды:

$ npm run dev # режим разработки http://localhost:8080
$ npm run build # сборка готовых ассетов и файлов в ./dist


Создадим файлы конфигурации терминальной магией:
$ touch webpack.config.js # корневой файл конфигурации обрабатываемый webpack
$ mkdir config # директория с конфигурациями
$ cd $_ # перейдем
$ touch global.js # общие настройки инструментов, загрузчиков и плагинов
$ mkdir env && cd $_
$ touch development.js # файл с 'тонкой' настройкой webpack для режима разработки
$ touch production.js # аналогичный файл для конечной сборки


Перейдем к настройке окружения, для этого откроем файл ./webpack.config.js и заполним следующим содержимым:
'use strict';

var _ = require('lodash');
var _configs = {
  global: require(__dirname + '/config/global'),
  production: require(__dirname + '/config/env/production'),
  development: require(__dirname + '/config/env/development')
};

var _load = function(environment) {
  // Проверяем окружение
  if (!environment) throw 'Can\'t find local environment variable via process.env.NODE_ENV';
  if (!_configs[environment]) throw 'Can\'t find environments see _config object';

  // load config file by environment
  return _configs && _.merge(
    _configs[environment](__dirname),
    _configs['global'](__dirname)
  );
};

/**
 * Export WebPack config
 * @type {[type]}
 */
module.exports = _load(process.env.NODE_ENV);



Как вы заметили lodash, исправим его отсутствие выполнением следующей команды:
$ npm i lodash --save-dev


Немного схитрив, мы сможем используя метод merge – библитеки lodash, 'склеить' нужную нам исходную конфигурацию, используя для этого 2 файла. В качестве аргумента функции принимая process.env.

./config/global.js


Файл содержит ненормативную лексику почти всю логику работы сборщика, следовательно к его содержимому нужно отнестись более ответственно:

'use strict'

var path        = require('path');
var webpack     = require('webpack');
var Manifest    = require('manifest-revision-webpack-plugin');
var TextPlugin  = require('extract-text-webpack-plugin');
var HtmlPlugin    = require('html-webpack-plugin');

module.exports = function(_path) {

  //define local variables
  var dependencies  = Object.keys(require(_path + '/package').dependencies);
  var rootAssetPath = _path + 'app';

  return {
    // точки входа
    entry: {
      application: _path + '/app/app.js',
      vendors: dependencies
    },

    // то, что получим на выходе
    output: {
      path: path.join(_path, 'dist'),
      filename: path.join('assets', 'js', '[name].bundle.[chunkhash].js'),
      chunkFilename: '[id].bundle.[chunkhash].js',
      publicPath: '/'
    },

    // Небольшие настройки связанные с тем, где искать сторонние библиотеки
    resolve: {
      extensions: ['', '.js'],
      modulesDirectories: ['node_modules'],
      // Алиасы - очень важный инструмент для определения области видимости ex. require('_modules/test/index')
      alias: {
        _svg:         path.join(_path, 'app', 'assets', 'svg'),
        _data:        path.join(_path, 'app', 'data'),
        _fonts:       path.join(_path, 'app', 'assets', 'fonts'),
        _modules:     path.join(_path, 'app', 'modules'),
        _images:      path.join(_path, 'app', 'assets', 'images'),
        _stylesheets: path.join(_path, 'app', 'assets', 'stylesheets'),
        _templates:   path.join(_path, 'app', 'assets', 'templates')
      }
    },
    // Настройка загрузчиков, они выполняют роль обработчика исходного файла в конечный
    module: {
      loaders: [
        { test: /\.jade$/, loader: 'jade-loader' },
        { test: /\.(css|ttf|eot|woff|woff2|png|ico|jpg|jpeg|gif|svg)$/i, loaders: ['file?context=' + rootAssetPath + '&name=assets/static/[ext]/[name].[hash].[ext]'] },
        { test: /\.styl$/, loader: TextPlugin.extract('style-loader', 'css-loader!autoprefixer-loader?browsers=last 5 version!stylus-loader') }
      ]
    },

    // загружаем плагины
    plugins: [
      new webpack.optimize.CommonsChunkPlugin('vendors', 'assets/js/vendors.[hash].js'),
      new TextPlugin('assets/css/[name].[hash].css'),
      new Manifest(path.join(_path + '/config', 'manifest.json'), {
        rootAssetPath: rootAssetPath
      }),
      // Этот файл будет являться "корневым" index.html
      new HtmlPlugin({
        title: 'Test APP',
        chunks: ['application', 'vendors'],
        filename: 'index.html',
        template: path.join(_path, 'app', 'index.html')
      })
    ]
  }
};


Аттеншен господа!
Появились новые зависимости – которые нужно доставить в проект следующей командой:
$ npm i path manifest-revision-webpack-plugin extract-text-webpack-plugin html-webpack-plugin --save-dev


Разработка


Методом проб и ошибок, оптимальный для меня конфиг режима разработки – стал выглядеть следующим образом:

'use strict';

/**
 * Development config
 */
module.exports = function(_path) {

  return {
    context: _path,
    debug: true,
    devtool: 'eval',
    devServer: {
      contentBase: './dist',
      info: true,
      hot: false,
      inline: true
    }
  }
};


Окончательная сборка


А вот настройка конечное сборки все еще в стадии «изменений». Хотя работает на 5+

'use strict';

/**
 * Production config
 */
module.exports = function(_path) {
  return {
    context: _path,
    debug: false,
    devtool: 'cheap-source-map',
    output: {
      publicPath: '/'
    }
  }
}


index.html


Этот шаблон, мы положим в папку ./app/index.html – именно он будет отдавать правильные пути до хешированной статики, после конечной сборки.

<!DOCTYPE html>
<html{% if(o.htmlWebpackPlugin.files.manifest) { %} manifest="{%= o.htmlWebpackPlugin.files.manifest %}"{% } %}>
  <head>
    <meta charset="UTF-8">
    <title>{%=o.htmlWebpackPlugin.options.title || 'Webpack App'%}</title>
    {% for (var css in o.htmlWebpackPlugin.files.css) { %}
      <link href="{%=o.htmlWebpackPlugin.files.css[css] %}" rel="stylesheet">
    {% } %}
  </head>
  <body>
    {% for (var chunk in o.htmlWebpackPlugin.files.chunks) { %}
    <script src="{%=o.htmlWebpackPlugin.files.chunks[chunk].entry %}"></script>
    {% } %}
  </body>
</html>


В заключении


Хотелось бы поблагодарить разработчиков webpack за столь мощный инструмент.
Скорость его работы действительно поражает, даже на больших объемах исходных файлов.

Ах, да. Для того чтобы в своем проекте использовать например underscore достаточно установить его привычной npm командой
$ npm i underscore --save


После выполнения, библиотека попадет в dependencies – следовательно webpack, поместит его содержимое в файл vendors.[hash].js при этом захеширует название файла полученное от md5 размера исходников + время последнего их изменения.

Для чего это надо, объяснять не буду.
На этом все, пробуйте, пишите комменты.
Спасибо.

Ссылки


Тут можно посмотреть код приведенный в статье
А тут ознакомиться с документацией по проекту
Ну и тут статья, которая поможет разложить все еще раз.

Комментарии (55)


  1. Delphinum
    31.08.2015 14:34

    Как то начал его пользовать, но закончил тем, что не смог решить на нем одну простую задачу, а именно:
    необходимо было разделить весь JS на несколько файлов так, чтобы основная логика была в одном файле, а несколько придаточных логик в других. При этом в зависимости от разрешений текущего пользователя, файлы нескольких придаточных логик загружать не должны были (ну или вместо них должны были загружаться заглушки).

    Может здесь подскажут, как это реализуется?


    1. mrsum
      31.08.2015 14:42
      +2

      Да конечно, это реализуется очень просто. Для этого Вам необходимо в файл конфигурации добавить еще один entrypoint. Рассмотрим ситуацию, когда есть скрипты основного приложения и скрипт формы авторизации:

      entry: {
        auth: _path + '/app/auth.js',
        app: _path + '/app/index.js',
        vendors: dependencies
      },
      new HtmlPlugin({
        title: 'App',
        chunks: ['app', 'vendors'],
        filename: 'index.html',
        template: 'app/index.html'
      }),
      new HtmlPlugin({
        title: 'Auth',
        chunks: ['auth', 'vendors'],
        filename: 'auth.html',
        template: 'app/auth.html'
      }),
      


      Вот и вся магия.


      1. Delphinum
        31.08.2015 14:52
        +1

        А как решается, когда подключать придаточную логику, а когда заглушку?


        1. mrsum
          31.08.2015 15:18

          Подразумевается что вызов require() в каждом entry point — подтянет только ту логику, которая будет там использована.
          Отвечая на Ваш вопрос – самостоятельно =)


          1. Delphinum
            31.08.2015 15:26

            Так задача не в том, подтягивать ли логику или не подтягивать в зависимости от необходимости. Ограничения такие: если заходит пользователь с currentUser.role != 'admin', то ему загружается в качестве модуля 'admin' файл 'public/js/mock/admin.js', а если пользователь с currentUser.role == 'admin', то ему загружается файл 'public/js/admin.js'. Более того, если пользователь не является админом и попробует открывать все файлы js, которые найдет, он не должен найти адрес файла 'public/js/admin.js'. То есть для «не админа» в результирующем js файле (файлах) не должно быть ссылок на 'public/js/admin.js'.


            1. mrsum
              31.08.2015 16:13

              Если не секрет, почему Вы эту логику не хотите реализовать через ACL?


              1. Delphinum
                31.08.2015 18:02

                Так речь об обычном web-сайте. Вы предлагаете прикрутить ACL к nginx?


        1. geakstr
          31.08.2015 15:21

          del


      1. cyber_ua
        31.08.2015 15:19

        А как вы решаете проблему с круговыми зависимостями?


        1. mrsum
          31.08.2015 16:15
          +2

          Мне кажется или это проблема архитектуры конкретного приложения?


          1. auine
            31.08.2015 16:49

            Циклическими*
            Нет, это не проблема приложения, просто такое бывает необходимо :))

            Я вижу сотни любителей вебпака, но ни один мне не может ответим, чем же этот толстый вебпак, лучше, удобней того же require.js, который поддерживает все тоже самое, и даже больше. Хоть не из коробки


            1. Delphinum
              31.08.2015 18:04

              Так require.js и webpack это два совершенно разных инструмента. Второй умеет собирать проект в статичный файл, оптимизировать его, добавлять хэши и тому подобное. Webpack лучше уж сравнивать с Grunt, чем с requireJS.


              1. auine
                31.08.2015 18:21
                +1

                require так же умеет собирать, в том числе и html.

                requirejs.org/docs/optimization.html.

                Grunt'ом можно рулить вебпакт, но не сравнивать :)


                1. Delphinum
                  31.08.2015 18:22

                  Так это же просто оптимизация, а для сборки может потребоваться еще много чего, разве нет?


                  1. auine
                    31.08.2015 18:25

                    Прочитайте цели, который там написаны. Прежде чем задавать еще один вопрос :))

                    RequireJS has an optimization tool that does the following
                    Combines related scripts together into build layers and minifies them via UglifyJS (the default) or Closure Compiler (an option when using Java).
                    Optimizes CSS by inlining CSS files referenced by import and removing comments.

                    Так же повторюсь html и все, что вам угодно. При этом с require можно не билдить в дев окружении


                    1. Delphinum
                      31.08.2015 18:32

                      Возможно я плохо задал вопрос и вы таки меня тыкните носом, чему я буду очень признателен, но где предварительная компиляция Sass, CoffeeScript, добавление хэшей к измененным файла, дробление на куски и подобный функционал, необходимый любому инструменту сборки? В целях, которые там написаны, я вижу только оптимизацию JS и CSS.


                      1. auine
                        31.08.2015 18:39

                        Хм, вебпак так же использует сторонние модули для работы с такими вещами?
                        В данном случае я отдаю такое напрямую в траспилиры и пре(пост)процессоры. С помощью таск ранера, например gulp или grunt. Собственно и сам require оптимизатор запускается галпом.
                        На этом моменте можно начать сравнивать у кого конфиг меньше и что более популярно :))
                        webpack — 7к звезд, галп — 15к


                        1. Delphinum
                          31.08.2015 18:57

                          Хм, вебпак так же использует сторонние модули для работы с такими вещами?

                          В том то и разница, что Webpack — это инструмент, который объединяет несколько инструментов в один конвеер, который после выполняется над проектом и мы получаем результирующие js'ы, css'ы и html'ы. Он под это заточен, как и Grunt. С другой стороны, RequireJS это больше инструмент для подключения модулей. Ему даже не обязательно уметь оптимизировать и склеивать JS файлы (я считаю это лишним функционалом).
                          В данном случае я отдаю такое напрямую в траспилиры и пре(пост)процессоры. С помощью таск ранера, например gulp или grunt.

                          Я тоже (пользую Grunt), но вопрос не в этом. Не совсем верно сравнивать системы сборки проекта (таск ранеры, как вы их называете) и RequireJS, который по сути является инструментом загрузки зависимостей.


                          1. auine
                            31.08.2015 19:05

                            Во, гору спасибок вам, так понятней) Теперь можно холиварить webpack vs gulp плагинами :)

                            Ему даже не обязательно уметь оптимизировать и склеивать JS файлы (я считаю это лишним функционалом).

                            Ну тут как и browserify, ему нужен свой механик, что бы собрать все + html темлпейты в стиле AMD модулей, тоже я пока негде не видел)


                            1. Delphinum
                              31.08.2015 19:15

                              Теперь можно холиварить webpack vs gulp плагинами :)

                              Да что тут холиварить. Хотите программируемые инструменты, пользуйте Gulp, хотите непрограммируемые, пользуйте Webpack.


            1. RusSuckOFF
              31.08.2015 18:10

              Есть хорошая страничка со сравнением разных сборщиков webpack.github.io/docs/comparison.html


            1. GrizliK1988
              31.08.2015 18:15

              В том и дело, что не из коробки. Будучи абсолютным мастером в обращении с require.js нет необходимости использовать webpack. Но вся штука как раз в том, что вебпак не требует большого количества времени на изучение/кофигурирование. Сам недавно перевел ~500 js файлов на webpack.

              Циклические зависимости так же вполне можно решить.


              1. Delphinum
                31.08.2015 18:21
                +1

                Эмм… А что нужно такого знать про require.js? Элементарный инструмент ведь.


            1. mrsum
              31.08.2015 18:26

              Webpack это:
              – СommonJs
              – компонентность
              – быстрая скорость сборки
              – 100% доставка компонентов системы по первому вызову
              – Пре- и пост- процессоры
              – Минификация
              – Сборка *.map файлов
              – Хеширование конечных файлов
              – и еще десятки пунктов…

              Из коробки. Вот чем webpack хорош


              1. auine
                31.08.2015 18:30

                Абсолютно тоже самое из коробки делает и умеет require.js. Увы месье — не удивили :)
                Так же CommonJs Modules, а то не понятно, что вы ввиду имеете. Стандарт сверверного js или стиль подключения модулей.


                1. dfuse
                  29.09.2015 08:09

                  RequireJS не умеет подключать файлы без явного указания плагина (css!./path/to.css).
                  RequireJS не умеет без диких плясок с бубном работать с TypeScript/ES6/Coffee/JADE/SASS, ему надо либо прекомпиляци, либо опять же плагины, а в вебпаке это делается за минуту.

                  Я создал две одинаковых системы для дичайше огромного сайта и пришел к выводу, что Webpack удобнее, т.к. позволяет на клиенте видеть и при разработке и после билда максимально идентичное окружение. Кол-во багов, которое вылезало из-за разницы в работе на живую и после сборки, было немного удручающим…

                  Я согласен, что эти два инструмента отличаются буквально в мелочах, но на больших проектах с множеством команд, эти мелочи выливаются в часы и дни.


            1. gbezyuk
              31.08.2015 18:44

              А hot reloading require.js умеет?


              1. auine
                31.08.2015 18:50

                То есть подключив левый плагин, в терминах webpack — модуль, настроив hot релоад уже означает, что я точно так же не могу подключить его к галпу? Или об этом в туториалах не пишут? :)


                1. gbezyuk
                  31.08.2015 19:16

                  я просто спросил. webpack это умеет из коробки dev-server'ом, и этим активно пользуется, например, Dan Abramov в своём redux-devtools.


        1. Eternalko
          31.08.2015 23:32

          Webpack решает их так же как и node.js


          1. cyber_ua
            01.09.2015 00:17

            Можно пример?
            Например, у меня есть файл
            a.js

            module.exports = {
                x: require( "./x" ),
                b: require( "./b" )
            };
            


            x.js
            var z = require( "./z" ) ; 
            //...
            


            z.js
            var  b = require( "./a" ).b
            //...
            

            я знаю что на прямую могу подключить b, но можно ли как то решить такую ситуацию не меняя код?


            1. Eternalko
              01.09.2015 11:51

              Вопроса не понял. А в чем проблема? Вы пробовали это запустить?

              Если коротко, то я не вижу тут проблем. Если у вас логические зависимости — исполнение кода одного модуля зависит от исполнения кода другого модуля и обратно, то у вас есть 2 выбора:

              — Поменять структуру
              — Использовать паттерн Message Broker.

              Советую второе.


    1. Eternalko
      31.08.2015 23:31

      В любом месте:

      if (userAccess) {
        require.ensure(['secret', 'superpupersecret'], function (require){
          var supersecret = require('secret');
          supersecret.launchNuke();
        }); 
      else {
        alert('you shall not pass');
      }
      
      


      1. cyber_ua
        01.09.2015 00:19
        -1

        Насчет ensure, как для ensure указать ссылку на cdn ??
        Я пробывал просто вставить

         require.ensure(['https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js', 'superpupersecret'], function (require){
            var supersecret = require('secret');
            supersecret.launchNuke();
          }); 
        


        1. Eternalko
          01.09.2015 11:43

          А вы чего ожидаете? Что он соберет chunk во время компиляции или в во время рантайма только вещи из URL будет скачивать?

          Правильное решение такого рода проблем:

          npm install angular --save
          



          1. cyber_ua
            02.09.2015 11:19

            Я хочу динамически подключать скрипт если нужно, ensure и так подключает скрипт динамически, интересно можно ли подключить скрипт по ссылке например.


          1. cyber_ua
            02.09.2015 11:20

            del


      1. Delphinum
        01.09.2015 01:15

        А заглушку то как подгрузить и скрыть адрес «secret» файла в путях?


        1. Eternalko
          01.09.2015 11:40

          Не понял вопроса.


          1. Delphinum
            01.09.2015 13:00
            +1

            Я объясню задачу еще раз и постараюсь более точно.

            Предположим у нас есть кучка JS файлов, которые после сборки превращатся в 'core.js' файл. В этом файле активно используется модуль 'admin' (файл 'admin.js'). Используется этот модуль как и положено, через объявление зависимостей. Файл это ('admin.js') так же собирается из некоторой кучки файлов.

            Для обеспечение безопасности, определены следующие два ограничения:
            1. Если пользователь, который посетил страницу, не является админом, ему под модулем 'admin' должен загружаться модуль заглушка (он в файле 'mock/admin.js')
            2. Если пользователь, который посетил страницу, не является админом, открыв файлы 'core.js' через браузер (исходники), или файл 'mock/admin.js', он не должен найти в этих файлах каких либо ссылок или чего либо, что позволило бы ему найти файл 'admin.js' и посмотреть его исходники


            1. Eternalko
              01.09.2015 13:36

              Если валидация происходит на стороне JS то это невозможно сделать. В теории.
              Вы прячете URL в стоге сена. А у меня есть большой магнит.

              Разве сервер может шаманить и раздавать разный файл в зависимости от сессии.

              Если это просто Security through obscurity то пройдитесь обсфукатором и делов то.


              1. Delphinum
                01.09.2015 13:40

                Если валидация происходит на стороне JS то это невозможно сделать.

                На стороне сервера тоже можно, это не принципиально. Проблема в том, что webpack не может сложить проект так, чтобы в нем не осталось ссылок на подключаемые модули (либо я не понял, как это сделать).


                1. Kongo
                  01.09.2015 15:42

                  Это выглядит как задача, которую webpack решать не призван. Он отделил модуль, который используется только в определенных сценариях (admin.js), а вот ограничить доступ к нему можно с помощью других инструментов. Например, используя сервер приложения и x-accel-redirect для nginx.


                  1. Delphinum
                    01.09.2015 16:48

                    Это выглядит как задача, которую webpack решать не призван.

                    Ну когда я выбираю систему сборки, меня мало волнует, что некоторый инструмент, называемый системой сборки, не призван решать мои задачи, согласитесь? )
                    а вот ограничить доступ к нему можно с помощью других инструментов

                    А можно просто на стороне сервера заменить один файл другим при подключении JS к странице, и никакой больше магии.


                    1. Kongo
                      01.09.2015 17:41

                      Динамическое ограничение доступа к файлам не выглядит как задача для системы сборки (webpack только частный случай), на мой взгляд.
                      Подмена файла больше похожа на магию, чем использование рассчитанных на это инструментов. Впрочем, как её предлагается устроить? Я предлагал делать проверку статуса на сервере приложения с последующим запросом к реверс-прокси на перенаправление к нужному скрипту, что несколько похоже на «подмену» файла.
                      В любом случае, у меня создалось впечатление, что вы рассматриваете сборку, как нечто динамическое. Вот пришел авторизованный клиент, собираем для него админский набор. Иначе — собираем другой. Но сборка-то едина и статична для всех сценариев.


                      1. Delphinum
                        01.09.2015 17:46

                        Не совсем так. Просто у webpack проблема в том, что его пытаются сделать «слишком умным». С одной стороны это удобно, так как не нужно ничего настраивать руками, все есть из коробки, но когда сталкиваешься с подобными задачами понимаешь, что это не панацея.

                        Проблема здесь не в том, что нужно что то делать в зависимости от ситуации, а в том, что нельзя скрыть от пользователя пути к JS файлам (если эти файлы не нужны пользователю) используя webpack.


                1. Eternalko
                  02.09.2015 00:33

                  это не принципиально.
                  Принципиально.

                  Это отделяет возможную к решению задачу от невозможной даже в теории.


                  1. Delphinum
                    02.09.2015 00:49
                    -1

                    Принципиально.

                    Не принципиально, так как проблема, которую я пытаюсь описать, не связана с этим.


                1. Eternalko
                  02.09.2015 00:38

                  Проблема в том, что webpack не может сложить проект так, чтобы в нем не осталось ссылок на подключаемые модули (либо я не понял, как это сделать).

                  webpack может.

                  // config.js
                  
                  {
                    entry: {
                      app: 'app.js',
                      output: {
                        path: __dirname + "/build/dev/",
                        publicPath: "/scripts/",
                        filename: '[name].js',
                        chunkFilename: '[name].js', // !!!!!!!!!
                      },
                      target: 'web'
                  }
                  
                  
                  // app.js
                  
                  var nm;
                  nm = require('normal.js');
                  
                  
                  require.ensure(["secret"], function(require) {
                    var secret = require('secret.js');
                    return console.log(adm);
                  }, 'SecretName'); // !!!!!!!!!
                  
                  


                  /build/dev/
                  - app.js
                  - SecretName.js
                  

                  И 2 раза собрать с FeatureFlags где один раз будет заглушка а второй раз нормальный файл.

                  А дальше 10 строчек колдовства на сервере и все.

                  росто у webpack проблема в том, что его пытаются сделать «слишком умным».

                  webpack тупой как пробка. Не надо вводить людей в заблуждение.


                  1. Delphinum
                    02.09.2015 00:50

                    И 2 раза собрать с FeatureFlags где один раз будет заглушка а второй раз нормальный файл.

                    А можно не собирать 2 раза, так как таких модулей, как 'admin', может быть больше чем 1 )
                    webpack тупой как пробка

                    Тупой как пробла Grunt, его нужно всему учить, а webpack вполне ученый.


                    1. Eternalko
                      02.09.2015 01:37

                      А можно не собирать 2 раза, так как таких модулей, как 'admin', может быть больше чем 1 )

                      Можно. Только дальше уже сами.


                      1. Delphinum
                        02.09.2015 01:49

                        Потому и не стал пользовать webpack.


                        1. Eternalko
                          02.09.2015 10:30

                          Зачем тогда спрашивали?


                          1. Delphinum
                            02.09.2015 13:04

                            Я же писал выше — мне было интересно, это я такой глупый, или webpack не может.


                            1. Eternalko
                              03.09.2015 23:18

                              Ага. Ну хорошо что все разъяснилось.