Приложение Bundle Angular 2, использующее пакеты UMD (не создает пакет поставщика)

В настоящее время я связываю свое приложение Angular 2 с WebPack. Мы по-прежнему развиваем быстрые циклы, поэтому вместо добавления задержек в процесс сборки и загрузки приложений мы хотим включить редко меняющиеся подготовленные пакеты Angular 2 UMD CDN, например:

<script src="https://npmcdn.com/@angular/[email protected]/bundles/core.umd.min.js"></script>
<script src="https://npmcdn.com/@angular/[email protected]/bundles/common.umd.min.js"></script>
<script src="https://npmcdn.com/@angular/[email protected]/bundles/compiler.umd.min.js"></script>
Когда я просто позволяю WebPack делать свое дело, пакет работает нормально, но занимает несколько МБ, потому что он не использует готовые пакеты и не выделяет код Angular 2 «vendor».Когда я используюAngular 2 WebPack РекомендацииНапример:plugins: [ new webpack.optimize.CommonsChunkPlugin("vendor", "vendor.bundle.js") ]Мой пакет приложений небольшой, но я вручную создаю отдельный уникальный пакет объемом 1 МБ, содержащий большую часть среды Angular 2, каждую сборку. Этот файл слегка изменяется при каждой сборке, в зависимости от моего приложения, и не переносится между версиями моих приложений или различными приложениями и не имеет преимущества «CDN». Конечно, я должен включить этот файл для запуска моего приложения.Когда я использую IgnorePlugin для фильтрации@angular|rxjsнапример,plugins: [ new webpack.IgnorePlugin(/\@angular|rxjs/) ], он исключает файлы поставщика, но вставляет жестко запрограммированные исключения / выбрасывает ошибки в начало моего пакета приложений.Когда я используюWebPack externalsнапример,externals: ['@angular/core', ..., Я получилfunction(module, exports) { module.exports = @angular/core; }, вывод в моем комплекте приложений, который, очевидно, не работает. Документация WebPack не так уж и доступна, но я думаю, что я могу либо указатьlibraryTarget или указанная функция разрешения, которая инструктирует WebPack компилировать при загрузке модуля.Когда я полностью отказываюсь от WebPack и использую вместо этого компилятор компилятора TypeScript (согласноэто руководство, который использует пакеты UMD), я получаюSystem.register() звонки, относящиеся к пространствам имен NPM, которые я ожидал, например,System.register("myapp/boot", ['@angular/core', ..., но я все еще работаю над настройкой SystemJS для вызова UMD. Как примечание, этот файл имеет дополнительные 25% размера по сравнению с тем, что генерирует WebPack.Если я использую SystemJS, как в предыдущем пункте, я хочу, чтобы эта компиляция происходила во время сборки или как параллельный процесс, а не как часть сохранения файла. ПохожеSystemJS-строитель (см. связанные вопросыВот а такжеВот) будет ли способ сделать это? Возможно, это также приведет к меньшим размерам файлов, чем встроенный в Typescript «упаковщик».

Как создать пакет приложений, который не зависит от уникально переупакованного пакета Angular 2?

Я сейчас строю против RC3. Мой процесс в настоящее время WebPack, как упоминалось выше, но я бы перешел к другому набору инструментов, если это облегчает.

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

Чтобы назначить пространства имен модуля UMD-пакетов (и подключить их), они не могут быть загружены в теги сценария. Вместо этого они должны быть оценены с учетомthis контекст, чтобы действовать в качестве ссылки на модуль. Это означает, что даже если я хочу, чтобы они все загружались синхронно, мне все равно нужно настроить что-то еще, например SystemJS, чтобы загружать их по проводам, чтобы их контекст контролировался / переносился.

этоУгловой 2-х плункер рядом с тем, что я ищу. Он использует пакеты Angular 2 UMD, но не использует пакет RxJs, хотя это выглядит достаточно легко изменить, если я хочу всю библиотеку RxJs.

Ответы на вопрос(2)

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

var webpack = require('webpack');

module.exports = {
  entry: './src/main',
  output: {
    filename: 'bundle.js',
    path: 'bundles/app',
  },

  resolve: {
    extensions: ['', '.ts', '.js'],
    alias: {
        '@angular/common' : '@angular/common/common.umd.js',
        '@angular/compiler' : '@angular/compiler/compiler.umd.js',
        '@angular/core' : '@angular/core/core.umd.js',
        '@angular/http' : '@angular/http/http.umd.js',
        '@angular/platform-browser' : '@angular/platform-browser/platform-browser.umd.,js',
        '@angular/platform-browser-dynamic' : '@angular/platform-browser-dynamic/platform-browser-dynamic.umd.js',
        '@angular/router' : '@angular/router/router.umd.js',
        '@angular/router-deprecated' : '@angular/router-deprecated/router-deprecated.umd.js',
        '@angular/upgrade' : '@angular/upgrade/upgrade.umd.js',
        'rxjs/Observable' : 'rxjs/bundles/Rx.umd.min.js',
        'rxjs/add/operator/map' : 'rxjs/bundles/Rx.umd.min.js',
        'rxjs/add/observable/fromEvent' : 'rxjs/bundles/Rx.umd.min.js',
        rxjs : 'rxjs/bundles/Rx.umd.min.js'
    }
  },

  module: {
    loaders: [
      {test: /\.ts$/, exclude: /node_modules/, loader: 'ts'},
    ],
    noParse: [/@angular/, /rxjs/]
  },

};

Основные конфигурации здесьnoParse а такжеresolve/alias, Я говорю веб-пакету загружать предварительно собранные пакеты UMD всякий раз, когда он находит такие требования, как@angular/common и так далее.

Эта конфигурация заставляет webpack включать файлы UMD вместо обработки каждого файла angular и rxjs. Моей целью было улучшить время сборки. Тем не менее, в моем случае мое приложение не удалось во время выполнения. Я думаю, что я использовал библиотеку, которая требует угловых файлов на егоsrc папки, и это сделало его неудачным. Я бы попробовал эту настройку проверить, работает ли она по вашему сценарию.

В качестве второй попытки я попробовал функцию под названиемWebpack DLL как описано вhttp://engineering.invisionapp.com/post/optimizing-webpack/, Он создал пакет, который можно повторно использовать в разных сборках, что позволяет избежать повторного объединения angular2 каждый раз. К сожалению, мое приложение не работает с исключениями внедрения зависимостей в этом сценарии.

Мне удалось загрузить пакеты UMD, используяSystemJS вместо Webpack, со следующей настройкой

(function(global) {

  var paths = {
    'jquery' : '../node_modules/jquery/dist/jquery.js',
    'bootstrap' : '../node_modules/bootstrap/dist/js/bootstrap.js',
    //'rxjs/*' : '../node_modules/rxjs/bundles/Rx.umd.min.js', //FAILS with router 3.0
  }

  var map = {
    'app':                        'app', // 'dist',
    'angular2-in-memory-web-api': '../node_modules/angular2-in-memory-web-api',
    '@angular':                   '../node_modules/@angular',
    'lodash':                     '../node_modules/lodash',
    'rxjs':                       '../node_modules/rxjs'    
  };

  var packages = {
    'app':                        { main: 'main.js',  defaultExtension: 'js' },
    'angular2-in-memory-web-api': { defaultExtension: 'js' },
    'lodash':                     { main: 'lodash.js', defaultExtension: 'js' },
    'rxjs':                       { defaultExtension: 'js' },
  };

  var ngPackageNames = [
    'common',
    'compiler',
    'core',
    'http',
    'platform-browser',
    'platform-browser-dynamic',
    'router',
    'router-deprecated',
    'upgrade',
  ];
  ngPackageNames.forEach(function(pkgName) {
    packages['@angular/'+pkgName] = { main: '/bundles/' + pkgName + '.umd.js', defaultExtension: 'js' };
  });

  var config = {
    map: map,
    packages: packages,
    paths : paths,
  };

  // filterSystemConfig - index.html's chance to modify config before we register it.
  if (global.filterSystemConfig) { global.filterSystemConfig(config); }

  System.config(config);

})(this);

Это довольно милая установка, предложенная официальными документами Angular2 с добавлениемpath раздел. Раньше можно было загружатьRxJS как единый пакет UMD, но с недавним представлением маршрутизатора 3.0 эта установка завершается неудачно с исключениями в коде маршрутизатора. Я должен был вернуться и загрузитьRxJS как индивидуальные запросы снова.

 shannon07 июл. 2016 г., 15:43
RxJ с UMD-пакетами всегда имели проблемы в Angular 2, как AFAIK. увидетьgithub.com/angular/angular/issues/9359
 shannon07 июл. 2016 г., 03:56
Обратите внимание, что я регулярно обновляю свои открытия в моем вопросе выше. Конечно, я дам ответ, если найду подходящее решение до того, как оно будет опубликовано.
 shannon06 июл. 2016 г., 23:34
Хотите поговорить об этом?
 Daniel Melo07 июл. 2016 г., 21:14
@shannon: на RxJS UMD с ng2: интересно. Я столкнулся только с проблемами, когда я представил новый новый маршрутизатор. Ну, мое приложение все еще маленькое, возможно, я случайно не столкнулся с какой-либо проблемой. На данный момент моей единственной целью было сокращение времени сборки. Поэтому я стараюсь все время избегать разбора и объединения ng2 / RxJS в webpack. Я вижу, у тебя больше целей, чем это. Я попробую вашу конфигурацию с помощью requirejs + webpack. Кажется, это делает трюк. Какие-либо проблемы, которые вы уже нашли с этим?
 shannon08 июл. 2016 г., 14:53
Нет, это работает для меня без проблем. С тех пор я попробовал несколько других методов только для сравнения, но похоже, что я оставлю это на следующие несколько месяцев. Дайте мне знать, если найдете что-нибудь получше!
 shannon07 июл. 2016 г., 20:30
Да, ваша конфигурация WebPack выше только что встроила файлы UMD. Может быть, это то, что вы хотели сделать, но это не то, что я пытался сделать. Я смог заставить это работать, но это, конечно, все еще приводит к полной очистке кэша каждого обновления. Я могу сделать это, когда мы замедлим количество выпусков, но тогда я также хочу включить тряску деревьев.
 shannon06 июл. 2016 г., 23:33
Да, он у меня теперь работает и с пакетами SystemJS, хотя я все еще используюrouter-deprecated, поэтому пока нет комментариев по этому вопросу, используя SystemJS-Builder. Ты так делаешь? Каким-то образом вам все еще нужно использовать пакеты UMD, код SystemJS, который вы показали, только настраивает их. Затем вы можете также сопоставить их с глобальными и вручную сопоставить с глобальными в конфигурации веб-пакета «Внешние», что похоже на то, что я сейчас пытаюсь (используя require.js только потому, что он меньше).
 shannon07 июл. 2016 г., 20:22
Кроме того, я вроде бы предполагаю, что вы на самом деле не реализовали свою идею «псевдонима»? Мне кажется, что псевдоним на самом деле не делает то, что вы думаете. Он просто заменяет имена в файлах, верно? И производственная версия все равно должна ссылаться на CDN. Так что лучший способ сделать это - один раз с помощью функции отображения модуля загрузчика. В моем ответе ниже я сделал это с помощью require.js (примечание: в угловых путях UMD отсутствует / bundle / part)
Решение Вопроса

удут, некоторые нет в настоящее время из-за дефектов в Angular 2. Вот подход, который я сейчас использую:

WebPack + require.js

angular2-WebPack-config.js

var config = {
    entry: {
        app: inputFile
    },
    externals: [
        /^@angular\//,
        /^rxjs\//
    ],
    output: {
        libraryTarget: "amd",
        path: __dirname,
        filename: './' + outputName
    },
    plugins: [
        new require('webpack').optimize.UglifyJsPlugin()
    ]
};

Я только говорю, что естьexternals и какой псевдостандартный механизм загрузит их во время выполнения черезlibraryTarget (AMD / RequireJS, CommonJs / узел, UMD). Моя настройка просто заставляет внешние ссылки библиотеки быть обернутыми вdefine().

Обратите внимание, что я ничего не делаю с путями в WebPack. В моем программном обеспечении, что-нибудь вnode_modules папка имеет аналогичный механизм ссылок как в моем программном обеспечении, так и в сторонних модулях, внутри. И мой код, и сторонние библиотеки ожидают найти RxJS наrxjs (например, а не../rxjs или 'node_modules / rxjs`). Во время выполнения оба должны быть отображены, но поскольку мы не позволяем WebPack получить доступ к сторонним модулям (мы используем предварительно созданные UMD), WebPack не место для этого сопоставления. Было бы только сопоставить мой код. Вместо этого мы должны сделать это в нашем загрузчике:

index.htm

<script src="https://npmcdn.com/core-js/client/shim.min.js"></script>
<script src="https://npmcdn.com/[email protected]/dist/zone.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/reflect-metadata/0.1.3/Reflect.min.js"></script>
<script>
    var require = (function(){
        var versions = {
            'router-deprecated': '@@2.0.0-rc.2',
            'forms': '@@0.1.1',
            'angular': '@@2.0.0-rc.4',
            'rxjs': '@@5.0.0-beta.10'
        }

        var paths = {
            'rxjs': "https://npmcdn.com/rxjs" + versions.rxjs + "/bundles/Rx.umd.min"
        };
        [
            'core',
            'http',
            'common',
            'compiler',
            'platform-browser',
            'router-deprecated',
            'platform-browser-dynamic'
        ].forEach(function (submodule) {
            var module = '@@angular/' + submodule
            paths[module] = 'https://npmcdn.com/' + module + (versions[submodule] || versions.angular) + '/bundles/' + submodule + '.umd.min';
        });

        var rxmap = {};
        [
            'Rx',
            'Observable',
            'Subject',
            'observable/PromiseObservable',
            'operator/toPromise'
        ].forEach(function (submodule) {
            rxmap['rxjs/' + submodule] = 'rxjs';
        })

        return {
            paths: paths,
            map: {
                '*': rxmap
            }
        };
    })();
</script>
<script data-main="../assets/compiled/a2.webpack.js" src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.2.0/require.min.js"></script>

Кроме того, поскольку, если вы используете WebPack и UMD, вы, вероятно, заботитесь о результирующих размерах и времени файлов. Процесс сборки Angular 2 этого под-приложения шел от 24 секунд до 1 секунды. Его размер публикации изменился с более чем 2 МБ до около 100 КБ.

Здесь приведены размеры нагрузки на провод кешированных зависимостей для справки. Странно у них сейчас несколько кбменьше в версии UMD, чем увеличение размера провода интегрированного, сокращенного пакета WebPack.

 KB
27.5 shim
 6.8 zone
 8.0 require
 3.3 platform-browser-dynamic
36.8 http
 8.7 core
20.8 common
16.5 router
98.5 compiler
27.9 platform-browser
39.0 Rx

Очевидно, что время загрузки моего общедоступного сайта после обновлений резко сокращается (до 1 секунды с 10-20 секунд), но эти цифры довольно сильно зависят от соединения.

Ваш ответ на вопрос