将 Angular2 HTML 和 TypeScript 构建到单个文件中

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/35867660/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 03:20:26  来源:igfitidea点击:

Build Angular2 HTML and TypeScript to a single file

angulartypescriptsystemjssystemjs-builder

提问by Stephen Wilson

I'm putting together an app (Large scale) using Angular2 and TypeScript. It will need to be divided into numerous projects and each project will have numerous components each with a .htmlview, .cssstylesheet and .tslogic / class.

我正在使用 Angular2 和 TypeScript 组合一个应用程序(大规模)。它需要被分成许多项目,每个项目将有许多组件,每个组件都有一个.html视图、.css样式表和.ts逻辑/类。

I would like each project to compile to a single *.jsfile and be copied to a host website which will run in IIS. This would be similar to how a WPF or Silverlight app is built with the .xamlfiles all getting compiled into the .dll.

我希望每个项目都编译为一个*.js文件并复制到将在 IIS 中运行的主机网站。这类似于 WPF 或 Silverlight 应用程序的构建方式,.xaml所有文件都被编译到.dll.

I've had a look around the web and am able to get the .tsfiles to build to a single .jsfile using the --outFileoption. But this doesn't help me with the .htmlfiles or the css.

我已经浏览了网络,并且能够使用该选项将.ts文件构建为单个.js文件--outFile。但这对我处理.html文件或css.

Any help would be greatly appreciated even if it's to say that what I'm asking is impossible :-)

任何帮助都将不胜感激,即使是说我要问的是不可能的:-)

Stephen

斯蒂芬

回答by martin

If you're using the default Angular2 tsconfig.jsonwith SystemJS loader:

如果您使用的是默认Angular2tsconfig.jsonSystemJS装载机

"module": "system",
"moduleResolution": "node",
...

You can leave all the heavy work on SystemJS Build Tool. This is for example how I do it in my projects using gulp:

您可以将所有繁重的工作留给 SystemJS Build Tool。例如,这是我如何在我的项目中使用gulp

  1. Compile *.ts and inline *.html templates

    I'm using gulp-angular-embed-templatesright away to inline all templateUrlinto templatestrings (this plugin works with both Angular 1.* and Angular 2).

    var tsc = require('gulp-typescript');
    var tsProject = tsc.createProject('tsconfig.json');
    var embedTemplates = require('gulp-angular-embed-templates');
    
    gulp.task('app.build', function () {
        var tsResult = gulp.src('app/src/**/*.ts', {base: './app/src'})
            .pipe(embedTemplates()) // inline templates
            .pipe(tsc(tsProject));
    
        return tsResult.js
            .pipe(gulp.dest('build/js'));
    });
    

    This will generate many anonymous System.register modulesin build/jsdirectory. All of them will have their templateUrlinlined already.

  2. Bundle everything into a single .jsfile

    I use SystemJS Build Toolfor this because I think it's way easier than using for example webpack. So, I have another gulp task for this to automate the process:

    var SystemBuilder = require('systemjs-builder');
    
    gulp.task('app.systemjs.bundle', function () {
        var builder = new SystemBuilder('build/js, {
            paths: {
                '*': '*.js'
            },
            meta: {
                'angular2/*': {
                    build: false
                },
                'rxjs/*': {
                    build: false
                }
            }
        });
    
        return builder.bundle('main', 'build/js/app.bundle.js');
    });
    

    The builder takes the same options as SystemJSso check their Config API.

    Calling builder.bundle('main', ...)searches for main.js(which is my initial script with Angular's bootstrapcall. It's the same file you can see in the 5 min quickstart) because I append .jsto all paths searched by the builder. This is because when you import a module in TS you usually call:

    import {ModalResultComponent} from './modal-result.component';
    

    which is compiled as ./modal-result.componentdependency and it doesn't care about the file extension. That's why I had to add *.jsto all paths to help builder find all compiled JavaScript files.

    The metaoptions just tell the builder to ignore dependencies that I don't want to bundle. That's Angular2 itself and rxjslibrary because I include import 'rxjs/add/operator/map'in main.ts.

    This generates a single app.bundle.jsfile with all modules registered as named modules using System.register.

  3. Using our app.bundle.js

    The last part is a piece of cake. We just import the default Angular2 stuff and then use bundleoptionto tell SystemJS where're all our dependencies.

    <script>
    System.config({
        packages: {
            '/web': {
                format: 'register',
                defaultExtension: 'js'
            }
        },
        bundles: {
            '/web/app.bundle': ['main']
        }
    });
    System.import('main').then(null, console.error.bind(console));
    </script>
    

    When we call System.import('main')it in fact first downloads /web/app.bundle.jsand registers all modules in the package and after that it imports modules mainwith our Angular2 bootstrap.

    And that's it!

  1. 编译 *.ts 和内联 *.html 模板

    我立即使用gulp-angular-embed-templates将所有内容内联templateUrltemplate字符串中(此插件适用于 Angular 1.* 和 Angular 2)。

    var tsc = require('gulp-typescript');
    var tsProject = tsc.createProject('tsconfig.json');
    var embedTemplates = require('gulp-angular-embed-templates');
    
    gulp.task('app.build', function () {
        var tsResult = gulp.src('app/src/**/*.ts', {base: './app/src'})
            .pipe(embedTemplates()) // inline templates
            .pipe(tsc(tsProject));
    
        return tsResult.js
            .pipe(gulp.dest('build/js'));
    });
    

    这将在目录中生成许多匿名 System.register 模块build/js。他们都已经templateUrl内联了。

  2. 将所有内容捆绑到一个.js文件中

    为此使用SystemJS 构建工具,因为我认为它比使用例如 webpack 更容易。所以,我有另一个吞咽任务来自动化这个过程:

    var SystemBuilder = require('systemjs-builder');
    
    gulp.task('app.systemjs.bundle', function () {
        var builder = new SystemBuilder('build/js, {
            paths: {
                '*': '*.js'
            },
            meta: {
                'angular2/*': {
                    build: false
                },
                'rxjs/*': {
                    build: false
                }
            }
        });
    
        return builder.bundle('main', 'build/js/app.bundle.js');
    });
    

    构建器采用与SystemJS相同的选项,因此请检查它们的Config API

    调用builder.bundle('main', ...)搜索main.js(这是我使用 Angularbootstrap调用的初始脚本。它与您在 5 分钟快速入门中可以看到的文件相同),因为我附加.js到构建器搜索的所有路径。这是因为当您在 TS 中导入模块时,您通常会调用:

    import {ModalResultComponent} from './modal-result.component';
    

    它被编译为./modal-result.component依赖项,它不关心文件扩展名。这就是为什么我必须添加*.js到所有路径以帮助构建器找到所有已编译的 JavaScript 文件。

    这些meta选项只是告诉构建器忽略我不想捆绑的依赖项。那是 Angular2 本身和rxjs库,因为我包含import 'rxjs/add/operator/map'main.ts.

    这会生成一个app.bundle.js文件,其中所有模块都使用System.register注册为命名模块。

  3. 使用我们的 app.bundle.js

    最后一部分是小菜一碟。我们只导入默认的 Angular2 内容,然后使用bundleoption告诉 SystemJS 我们所有的依赖在哪里。

    <script>
    System.config({
        packages: {
            '/web': {
                format: 'register',
                defaultExtension: 'js'
            }
        },
        bundles: {
            '/web/app.bundle': ['main']
        }
    });
    System.import('main').then(null, console.error.bind(console));
    </script>
    

    System.import('main')实际上,当我们调用它时,首先下载/web/app.bundle.js并注册包中的所有模块,然后main使用我们的 Angular2 引导程序导入模块。

    就是这样!

You actually don't need to use gulpat all and do everything with pure nodescript.

您实际上根本不需要使用gulpnode脚本并完成所有操作。

Bundling CSS files is easy with things like cssnanoand I'm sure you can find tutorials on how to use it everywhere.

使用cssnano 之类的东西捆绑 CSS 文件很容易,我相信您可以在任何地方找到有关如何使用它的教程。

I'm sure there're other ways to the the same thing. Angular2 is designed not to restrict you to use just one technology. However, using SystemJS seems to me to be the easiest way because it uses the same module system as Angular2 by default.

我敢肯定还有其他方法可以做同样的事情。Angular2 旨在不限制您只使用一种技术。然而,在我看来,使用 SystemJS 是最简单的方法,因为它默认使用与 Angular2 相同的模块系统。

I'm sure you could use also for example commonjsformat but that would require you to use also some polyfill for require()loader, but I haven't tried it yet. I belive UMDmight be also worth trying.

我确定您也可以使用例如commonjs格式,但这需要您还为require()加载程序使用一些 polyfill ,但我还没有尝试过。我相信UMD可能也值得一试。