【初始angular 】angular项目创建过程中需要注意的细节

安装angular-cli工具

yarn global add @angular/cli

当前使用版本:Angular CLI: 7.3.1

如果是一些企业级项目的话,笔者推荐使用的版本比官方最新版小一个主版本号,防止最新版一些未发现的问题

设置包管理工具为yarn

ng config cli.packageManager yarn -g

设置cli的包管理工具,这一步可有可无,你也可以用默认的npm

创建项目

ng new ng-project

ng 命令介绍 angular-cli

有两个选项,根据需求选择,以下是当前操作

? Would you like to add Angular routing? Yes
? Which stylesheet format would you like to use? Sass   [ http://sass-lang.com   ]

热更新

  1. 添加@angularclass/hmr包

    yarn add @angularclass/hmr --dev

  2. 创建src/hmr.ts文件

    import { NgModuleRef, ApplicationRef } from '@angular/core';
    import { createNewHosts } from '@angularclass/hmr';
    
    export const hmrBootstrap = (
      module: any,
      bootstrap: () => Promise<NgModuleRef<any>>
    ) => {
      let ngModule: NgModuleRef<any>;
      module.hot.accept();
      bootstrap().then(mod => (ngModule = mod));
      module.hot.dispose(() => {
        const appRef: ApplicationRef = ngModule.injector.get(ApplicationRef);
        const elements = appRef.components.map(c => c.location.nativeElement);
        const makeVisible = createNewHosts(elements);
        ngModule.destroy();
        makeVisible();
      });
    };
  3. 修改src/main.ts

    import { enableProdMode } from '@angular/core';
    import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
    import { AppModule } from './app/app.module';
    import { environment } from './environments/environment';
    import { hmrBootstrap } from './hmr';
    
    declare var module: any;
    
    if (environment.production) {
      enableProdMode();
    }
    
    const bootstrap = () => platformBrowserDynamic().bootstrapModule(AppModule);
    
    if ((environment as any).hmr) {
      if (module.hot) {
        hmrBootstrap(module, bootstrap);
      } else {
        console.error('HMR is not enabled for webpack-dev-job!');
        console.log('Are you using the --hmr flag for ng serve?');
      }
    } else {
      document.addEventListener('DOMContentLoaded', () => {
        bootstrap().catch(err => console.log(err));
      });
    }
  4. 创建src/environments/environment.hmr.ts

    export const environment = {
      production: false,
      hmr: true
    };
  5. 修改angular.json文件

    在angular.json的对象projects.architect.build.configurations添加以下内容

    "hmr": {
        "fileReplacements": [
            {
                "replace": "src/environments/environment.ts",
                "with": "src/environments/environment.hmr.ts"
            }
        ]
    }

    在angular.json的对象projects.architect.serve.configurations添加以下内容

    "hmr": {
        "browserTarget": "ng-project:build:hmr",
        "hmr": true
    }
  6. 添加热更新启动命令行

    在package.json的scripts中添加以下内容

    "start:hmr": "ng serve -c hmr"

多项目支持

ng generate application ng-project2

这个命令会在根目录下生产一个projects文件夹,所有生成的项目都在这个文件夹下

通过npm模块的方式引用外部依赖

比如ng-project项目和ng-project2需要共用api接口,我们想在在项目中以 @apis/user、@apis/permissions这样的方式使用api接口,两步:

  • 创建apis类库ng generate library apis
  • 在tsconfig.json中compilerOptions下添加

    "paths": {
        "@apis/*": [
            "dist/apis/*"
        ]
    }

服务端渲染

ng add @nguniversal/express-engine --clientProject ng-project --appId ng-project-universal

  • yarn add mutation-observer // 有些库需要比如:ng-zorro-antd
  • 替换 server.ts

    import 'zone.js/dist/zone-node';
    import 'reflect-metadata';
    import { enableProdMode } from '@angular/core';
    // Express Engine
    import { ngExpressEngine } from '@nguniversal/express-engine';
    // Import module map for lazy loading
    import { provideModuleMap } from '@nguniversal/module-map-ngfactory-loader';
    
    import * as express from 'express';
    import { join } from 'path';
    
    const domino = require('domino');
    const fs = require('fs');
    const template = fs.readFileSync(join(process.cwd(), 'dist/browser/index.html')).toString();
    const win = domino.createWindow(template);
    
    global['window'] = win;
    global['MutationObserver'] = require('mutation-observer');
    Object.defineProperty(win.document.body.style, 'transform', {
      value: () => {
        return {
          enumerable: true,
          configurable: true
        };
      },
    });
    
    global['document'] = win.document;
    global['CSS'] = null;
    
    // Faster server renders w/ Prod mode (dev mode never needed)
    enableProdMode();
    
    // Express server
    const app = express();
    
    const PORT = process.env.PORT || 4000;
    const DIST_FOLDER = join(process.cwd(), 'dist/browser');
    
    // * NOTE :: leave this as require() since this file is built Dynamically from webpack
    const {AppServerModuleNgFactory, LAZY_MODULE_MAP} = require('./dist/server/main');
    
    // Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine)
    app.engine('html', ngExpressEngine({
      bootstrap: AppServerModuleNgFactory,
      providers: [
        provideModuleMap(LAZY_MODULE_MAP)
      ]
    }));
    
    app.set('view engine', 'html');
    app.set('views', DIST_FOLDER);
    
    // Example Express Rest API endpoints
    // app.get('/api/**', (req, res) => { });
    // Server static files from /browser
    app.get('*.*', express.static(DIST_FOLDER, {
      maxAge: '1y'
    }));
    
    // All regular routes use the Universal engine
    app.get('*', (req, res) => {
      global['navigator'] = req['headers']['user-agent'];
      res.render('index', {req});
    });
    
    // Start up the Node server
    app.listen(PORT, () => {
      console.log(`Node Express server listening on http://localhost:${PORT}`);
    });
  • 替换src/app/app.server.module.ts

    import { NgModule } from '@angular/core';
    import { ServerModule, ServerTransferStateModule } from '@angular/platform-server';
    import { AppModule } from './app.module';
    import { AppComponent } from './app.component';
    import { ModuleMapLoaderModule } from '@nguniversal/module-map-ngfactory-loader';
    
    @NgModule({
      imports: [
        AppModule,
        ServerModule,
        ModuleMapLoaderModule,
        ServerTransferStateModule,
      ],
      bootstrap: [AppComponent],
    })
    export class AppServerModule {}
  • 构建 yarn build:ssr
  • 运行 serve:ssr
通过命令生产的 server.ts 不能解决一些浏览器报错的问题,以上的server.ts已经把大部分问题包含了

提供参考项目源码 https://github.com/loopbless/btf-factoring-manager

至此,一个逼格较高的angular项目就建好了!


range
4 声望0 粉丝