├── .gitignore ├── superstatic.json ├── src ├── favicon.ico ├── app │ ├── dynamicModule │ │ ├── dy1.component.ts │ │ ├── dy2.component.ts │ │ ├── dynamicModule.template.html │ │ ├── comMgr.ts │ │ ├── dynamicModule.scss │ │ ├── dynamicModule-routing.module.ts │ │ ├── dynamicModule.module.ts │ │ └── dynamic.component.ts │ ├── app.component.html │ ├── app.component.ts │ ├── core │ │ └── core.module.ts │ ├── app-routing.module.ts │ ├── app.component.scss │ ├── shared │ │ └── shared.module.ts │ └── app.module.ts ├── main.ts ├── polyfills.ts ├── index.html ├── vendor.ts └── assets │ └── styles │ └── index.scss ├── webpack.config.js ├── README.md ├── config ├── helpers.js ├── webpack.dev.js ├── webpack.prod.js └── webpack.common.js ├── tsconfig.json └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules/* 2 | /dist/* 3 | /.idea/ -------------------------------------------------------------------------------- /superstatic.json: -------------------------------------------------------------------------------- 1 | { 2 | "rewrites": [ 3 | {"source":"/*", "destination":"/index.html"} 4 | ] 5 | } -------------------------------------------------------------------------------- /src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuzhouyang/angular-dynamic-component-example/HEAD/src/favicon.ico -------------------------------------------------------------------------------- /src/app/dynamicModule/dy1.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core' 2 | 3 | @Component({ 4 | template:`动态组件1` 5 | }) 6 | export class DY1Component{} -------------------------------------------------------------------------------- /src/app/dynamicModule/dy2.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core' 2 | 3 | @Component({ 4 | template:`动态组件2` 5 | }) 6 | export class DY2Component{} -------------------------------------------------------------------------------- /src/app/app.component.html: -------------------------------------------------------------------------------- 1 |
2 | 动态创建模块 3 | 4 |
5 | 6 | -------------------------------------------------------------------------------- /src/app/dynamicModule/dynamicModule.template.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 |
5 |
-------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | switch (process.env.NODE_ENV) { 2 | //生产模式(aot) 3 | case 'prod': 4 | module.exports = require('./config/webpack.prod.js'); 5 | break; 6 | //开发模式 7 | case 'dev': 8 | default: 9 | module.exports = require('./config/webpack.dev.js'); 10 | } -------------------------------------------------------------------------------- /src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component} from '@angular/core' 2 | 3 | @Component({ 4 | selector: 'wzy-app', 5 | templateUrl: './app.component.html', 6 | styleUrls:[ 7 | './app.component.scss' 8 | ] 9 | }) 10 | export class AppComponent{ 11 | public constructor() {} 12 | } -------------------------------------------------------------------------------- /src/app/dynamicModule/comMgr.ts: -------------------------------------------------------------------------------- 1 | import { DY1Component } from './dy1.component' 2 | import { DY2Component } from './dy2.component' 3 | 4 | let coms={ 5 | DY1Component, 6 | DY2Component 7 | } 8 | const importComs = [ 9 | DY1Component, 10 | DY2Component 11 | ] 12 | 13 | export { coms, importComs } -------------------------------------------------------------------------------- /src/app/dynamicModule/dynamicModule.scss: -------------------------------------------------------------------------------- 1 | .dm{ 2 | width: 50%; 3 | margin: auto; 4 | .dmBtn{ 5 | background: rgba(255,255,255,.3); 6 | color:#fff; 7 | border:none; 8 | outline: none; 9 | padding: 10px; 10 | } 11 | .dmRoom{ 12 | margin-top: 10px; 13 | } 14 | } -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | //主入口文件 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic' 3 | import { enableProdMode } from '@angular/core' 4 | 5 | import { AppModule } from './app/app.module' 6 | 7 | import './assets/styles/index.scss' 8 | 9 | enableProdMode() 10 | platformBrowserDynamic().bootstrapModule(AppModule) -------------------------------------------------------------------------------- /src/polyfills.ts: -------------------------------------------------------------------------------- 1 | //填充物 2 | import 'core-js/es6' 3 | import 'core-js/es7/reflect' 4 | import 'zone.js/dist/zone' 5 | if (process.env.NODE_ENV === 'prod' || process.env.NODE_ENV === 'aot') { 6 | // Production 7 | } else { 8 | // Development 9 | Error['stackTraceLimit'] = Infinity 10 | require('zone.js/dist/long-stack-trace-zone') 11 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 动态加载(创建)组件例子 2 | 3 | 简书文章链接:http://www.jianshu.com/p/10feab2c3102 4 | 5 | ## usage of command line 命令行用法 6 | > `npm install` 7 | 8 | > #### develop(port:8111) ---- 开发(端口:8111) 9 | > `npm start` 10 | 11 | > #### aot、production(port:8112) ---- aot编译(端口:8112) 12 | 1. `npm run build` 13 | 2. `npm run server` 14 | -------------------------------------------------------------------------------- /config/helpers.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | //处理路径 __dirname表示当前文件所在的绝对路径 3 | //_root相当于 当前所在目录的上级 4 | var _root = path.resolve(__dirname, '..'); 5 | 6 | //根据传入的参数自动计算路径 7 | function root(args) { 8 | args = Array.prototype.slice.call(arguments, 0); 9 | return path.join.apply(path, [_root].concat(args)); 10 | } 11 | exports.root = root; -------------------------------------------------------------------------------- /src/app/core/core.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule , ModuleWithProviders } from '@angular/core' 2 | 3 | //核心模块,可在此配置全局服务 4 | //core module,you can provide some global services here 5 | @NgModule({ 6 | providers:[] 7 | }) 8 | export class CoreModule{ 9 | static forRoot():ModuleWithProviders{ 10 | return{ 11 | ngModule:CoreModule 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 应用加载中(loading)... 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/app/app-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core' 2 | import { Routes, RouterModule } from '@angular/router' 3 | 4 | const routes:Routes=[ 5 | { 6 | path:'dynamicModule', 7 | loadChildren:'./dynamicModule/dynamicModule.module#DynamicModule' 8 | } 9 | ] 10 | @NgModule({ 11 | imports:[ 12 | RouterModule.forRoot(routes) 13 | ], 14 | exports:[ 15 | RouterModule 16 | ] 17 | }) 18 | export class AppRoutingModule{} -------------------------------------------------------------------------------- /src/vendor.ts: -------------------------------------------------------------------------------- 1 | //第三方引用 2 | // RxJS 3 | // import 'rxjs'; 4 | // import 'rxjs/add/observable/throw' 5 | // import 'rxjs/add/observable/fromEvent' 6 | // import 'rxjs/add/observable/of' 7 | // import 'rxjs/add/operator/do' 8 | // import 'rxjs/add/operator/delay' 9 | // import 'rxjs/add/operator/catch' 10 | // import 'rxjs/add/operator/map' 11 | // import 'rxjs/add/operator/toPromise' 12 | // import 'rxjs/add/operator/distinctUntilChanged' 13 | // import 'rxjs/Subscription' -------------------------------------------------------------------------------- /src/assets/styles/index.scss: -------------------------------------------------------------------------------- 1 | @charset "UTF-8"; 2 | 3 | html,body{ 4 | height:100%; 5 | margin:0; 6 | font-size: 16px; 7 | font-family: "Microsoft YaHei",Serif; 8 | -webkit-font-smoothing: antialiased; 9 | -moz-osx-font-smoothing: grayscale; 10 | } 11 | *{ 12 | margin: 0; 13 | padding: 0; 14 | } 15 | .startSpan{ 16 | display: block; 17 | width:40%; 18 | margin: auto; 19 | text-align: center; 20 | padding-top: 100px; 21 | padding-bottom:30px; 22 | font-size: 1.8rem; 23 | border-bottom:1px solid #B5B5B5; 24 | } -------------------------------------------------------------------------------- /src/app/dynamicModule/dynamicModule-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core' 2 | import { Routes,RouterModule } from '@angular/router' 3 | 4 | import { DynamicComponent } from './dynamic.component' 5 | const routes:Routes=[ 6 | { 7 | path:'', 8 | component:DynamicComponent 9 | } 10 | ] 11 | 12 | @NgModule({ 13 | imports:[ 14 | RouterModule.forChild(routes) 15 | ], 16 | exports:[ 17 | RouterModule 18 | ] 19 | }) 20 | export class DynamicModuleRoutingModule{ 21 | } -------------------------------------------------------------------------------- /src/app/dynamicModule/dynamicModule.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core' 2 | 3 | import { DynamicComponent } from './dynamic.component' 4 | import { DynamicModuleRoutingModule } from './dynamicModule-routing.module' 5 | 6 | import { importComs } from './comMgr' 7 | 8 | @NgModule({ 9 | declarations:[ 10 | DynamicComponent, 11 | ...importComs 12 | ], 13 | entryComponents:[ 14 | ...importComs 15 | ], 16 | imports:[ 17 | DynamicModuleRoutingModule 18 | ] 19 | }) 20 | export class DynamicModule{} -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "commonjs", 5 | "moduleResolution": "node", 6 | "sourceMap": true, 7 | "emitDecoratorMetadata": true, 8 | "experimentalDecorators": true, 9 | "removeComments": true, 10 | "noImplicitAny": true, 11 | "suppressImplicitAnyIndexErrors": true, 12 | "typeRoots": [ 13 | "node_modules/@types" 14 | ] 15 | }, 16 | "exclude": [ 17 | "node_modules", 18 | "dist" 19 | ], 20 | "angularCompilerOptions": { 21 | "skipMetadataEmit": true 22 | } 23 | } -------------------------------------------------------------------------------- /src/app/app.component.scss: -------------------------------------------------------------------------------- 1 | .app{ 2 | width: 100%; 3 | padding-top: 50px; 4 | padding-bottom: 50px; 5 | text-align:center; 6 | color:rgba(255,255,255,.8); 7 | background-color: #4a99cc; 8 | background: linear-gradient( 9 | 45deg, 10 | #4a5ccc 30%, 11 | #3fc8b1 100% 12 | ); 13 | box-shadow: 0px -3px 10px rgba(0,0,0,0.2) inset; 14 | p{ 15 | padding-bottom: 10px; 16 | } 17 | a{ 18 | height: 30px; 19 | width: 200px; 20 | line-height: 30px; 21 | display: inline-block; 22 | text-decoration:none; 23 | padding: 5px; 24 | background: rgba(255,255,255,.3); 25 | color:rgba(255,255,255,.8); 26 | margin-bottom: 20px; 27 | } 28 | } -------------------------------------------------------------------------------- /config/webpack.dev.js: -------------------------------------------------------------------------------- 1 | //开发模式下 webpack 配置 2 | //develop webpack config 3 | var webpack=require('webpack') 4 | var webpackMerge = require('webpack-merge'); 5 | var ExtractTextPlugin = require('extract-text-webpack-plugin'); 6 | var commonConfig = require('./webpack.common.js'); 7 | var helpers = require('./helpers'); 8 | 9 | module.exports = webpackMerge(commonConfig, { 10 | devtool: 'cheap-module-eval-source-map', 11 | output: { 12 | path: helpers.root('dist'), 13 | publicPath: '', 14 | filename: '[name].js', 15 | chunkFilename: '[name].chunk.js' 16 | }, 17 | 18 | plugins: [ 19 | new ExtractTextPlugin('[name].css') 20 | ], 21 | 22 | devServer: { 23 | historyApiFallback: true, 24 | stats: 'minimal', 25 | host:'0.0.0.0', 26 | port: 8111, 27 | contentBase:'src/' 28 | }, 29 | }); -------------------------------------------------------------------------------- /src/app/shared/shared.module.ts: -------------------------------------------------------------------------------- 1 | import { CommonModule } from '@angular/common' 2 | import { FormsModule } from '@angular/forms' 3 | import { HttpModule,Http } from '@angular/http' 4 | import { NgModule,ModuleWithProviders } from '@angular/core' 5 | 6 | @NgModule({ 7 | imports:[ 8 | /* 引入一些此模块需要的其他模块 */ 9 | /* import some module that the shared module needs */ 10 | ], 11 | declarations:[ 12 | /* 声明一些属于shared module的组件或指令,在其他模块导入的时候便会生效 */ 13 | /* some shared component or directives */ 14 | ], 15 | exports:[ 16 | CommonModule, 17 | FormsModule, 18 | HttpModule 19 | /* 导出一些模块 这些模块是经常被使用的模块 其他模块导入shared module时便不用再次导入这些模块 */ 20 | /* export some module that always be used */ 21 | ] 22 | }) 23 | export class SharedModule{ 24 | static forRoot():ModuleWithProviders{ 25 | return { 26 | ngModule:SharedModule 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule, ApplicationRef } from '@angular/core' 2 | import { BrowserModule } from '@angular/platform-browser' 3 | import { 4 | removeNgStyles, 5 | createNewHosts, 6 | createInputTransfer 7 | } from '@angularclass/hmr' 8 | 9 | import { AppRoutingModule } from './app-routing.module' 10 | import { SharedModule } from './shared/shared.module' 11 | import { CoreModule } from './core/core.module' 12 | import { AppComponent } from './app.component' 13 | 14 | @NgModule({ 15 | declarations: [ 16 | AppComponent 17 | ], 18 | imports: [ 19 | AppRoutingModule, 20 | BrowserModule, 21 | CoreModule.forRoot(), 22 | SharedModule.forRoot() 23 | ], 24 | bootstrap: [ 25 | AppComponent 26 | ] 27 | }) 28 | // hmr config 29 | export class AppModule { 30 | constructor(public appRef: ApplicationRef) { } 31 | hmrOnInit(store:any) { 32 | } 33 | hmrOnDestroy(store:any) { 34 | let cmpLocation = this.appRef.components.map(cmp => cmp.location.nativeElement) 35 | store.disposeOldHosts = createNewHosts(cmpLocation) 36 | removeNgStyles() 37 | } 38 | hmrAfterDestroy(store:any) { 39 | store.disposeOldHosts() 40 | delete store.disposeOldHosts 41 | } 42 | } -------------------------------------------------------------------------------- /src/app/dynamicModule/dynamic.component.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Compiler, 3 | Component, 4 | ComponentFactory, 5 | ComponentFactoryResolver, 6 | Injector, 7 | NgModule, 8 | ReflectiveInjector, 9 | ViewChild, 10 | ViewContainerRef 11 | } from '@angular/core' 12 | import { COMPILER_PROVIDERS } from '@angular/compiler' 13 | 14 | import { coms } from './comMgr' 15 | 16 | @Component({ 17 | selector: 'dynamic-com', 18 | templateUrl: './dynamicModule.template.html', 19 | styleUrls: [ 20 | './dynamicModule.scss' 21 | ] 22 | }) 23 | export class DynamicComponent { 24 | @ViewChild('dmroom', { read: ViewContainerRef }) dmRoom: ViewContainerRef; 25 | 26 | private cp: Compiler 27 | 28 | constructor( 29 | private cfr: ComponentFactoryResolver, 30 | private ijt: Injector, 31 | ) { 32 | this.ijt = ReflectiveInjector.resolveAndCreate(COMPILER_PROVIDERS, ijt) 33 | this.cp = this.ijt.get(Compiler) 34 | } 35 | 36 | addComponent() { 37 | let com = this.cfr.resolveComponentFactory(coms['DY1Component']) 38 | this.dmRoom.createComponent(com) 39 | } 40 | 41 | createComponent() { 42 | this.dmRoom.createComponent(this.createModule()) 43 | } 44 | 45 | createModule(): ComponentFactory { 46 | @Component({ 47 | template: '动态组件' 48 | }) 49 | class DyCom { } 50 | 51 | @NgModule({ 52 | declarations: [ 53 | DyCom 54 | ] 55 | }) 56 | class DyModule { } 57 | 58 | return this.cp.compileModuleAndAllComponentsSync(DyModule).componentFactories 59 | .find(comFac => { 60 | return comFac.componentType === DyCom 61 | }) 62 | } 63 | } 64 | 65 | 66 | -------------------------------------------------------------------------------- /config/webpack.prod.js: -------------------------------------------------------------------------------- 1 | //生产环境下 webpack配置文件 2 | //production webpack config 3 | var webpack = require('webpack'); 4 | var webpackMerge = require('webpack-merge'); 5 | var ExtractTextPlugin = require('extract-text-webpack-plugin'); 6 | var commonConfig = require('./webpack.common'); 7 | var helpers = require('./helpers'); 8 | var ngtools = require('@ngtools/webpack'); 9 | 10 | var env=process.env.NODE_ENV; 11 | module.exports = webpackMerge(commonConfig, { 12 | output: { 13 | path: helpers.root('dist'), 14 | publicPath: '', 15 | filename: '[name].[hash].js', 16 | chunkFilename: '[id].[hash].chunk.js' 17 | }, 18 | plugins: [ 19 | new webpack.NoEmitOnErrorsPlugin(), 20 | new ExtractTextPlugin({ 21 | filename: '[name].[hash].css', 22 | disable: false, 23 | allChunks: true 24 | }), 25 | //最小化 (minify) 26 | new webpack.optimize.UglifyJsPlugin({ 27 | mangle: true, 28 | screw_ie8: true, 29 | beautify: false, 30 | comments: false, 31 | compress: { 32 | warnings: false, 33 | warnings: true, 34 | drop_console: false, 35 | collapse_vars: true, 36 | reduce_vars: true 37 | } 38 | }), 39 | new webpack.LoaderOptionsPlugin({ 40 | options: { 41 | htmlLoader: { 42 | minimize: false 43 | } 44 | } 45 | }), 46 | 47 | //ng2 aot webpack插件配置 48 | //ng2 aot webpack config 49 | new ngtools.AotPlugin({ 50 | tsConfigPath: './tsconfig.json', 51 | entryModule: helpers.root('src','app','app.module')+'#AppModule' 52 | }), 53 | 54 | new webpack.DefinePlugin({ 55 | 'process.env': { 56 | 'NODE_ENV': JSON.stringify(env) 57 | } 58 | }) 59 | ] 60 | }); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular4-seed-starter", 3 | "description": "an angular start design by wuzhouyang", 4 | "version": "1.0.1", 5 | "license": "MIT", 6 | "scripts": { 7 | "server": "superstatic dist/ --port 8112 --host 0.0.0.0 --gzip", 8 | "prestart": "cross-env NODE_ENV=dev", 9 | "start": "webpack-dev-server --progress --inline --hot", 10 | "prebuild": "rimraf dist", 11 | "build": "cross-env NODE_ENV=prod webpack --progress" 12 | }, 13 | "dependencies": { 14 | "@angular/animations": "4.0.0", 15 | "@angular/common": "4.0.0", 16 | "@angular/compiler": "4.0.0", 17 | "@angular/compiler-cli": "4.0.0", 18 | "@angular/core": "4.0.0", 19 | "@angular/forms": "4.0.0", 20 | "@angular/http": "4.0.0", 21 | "@angular/platform-browser": "4.0.0", 22 | "@angular/platform-browser-dynamic": "4.0.0", 23 | "@angular/router": "4.0.0", 24 | "core-js": "2.4.1", 25 | "ie-shim": "0.1.0", 26 | "reflect-metadata": "0.1.9", 27 | "rxjs": "5.0.1", 28 | "zone.js": "^0.8.4" 29 | }, 30 | "devDependencies": { 31 | "@angular/compiler-cli": "4.0.0", 32 | "@angular/platform-server": "4.0.0", 33 | "@angularclass/hmr": "^1.2.2", 34 | "@angularclass/hmr-loader": "^3.0.2", 35 | "@ngtools/webpack": "1.3.0", 36 | "@types/core-js": "^0.9.34", 37 | "@types/jasmine": "^2.2.34", 38 | "@types/node": "^6.0.40", 39 | "@types/webpack": "^1.12.35", 40 | "angular2-router-loader": "^0.3.5", 41 | "angular2-template-loader": "^0.6.2", 42 | "autoprefixer": "^6.4.1", 43 | "awesome-typescript-loader": "^3.1.2", 44 | "copy-webpack-plugin": "^4.0.1", 45 | "cross-env": "^3.1.3", 46 | "css-loader": "^0.25.0", 47 | "extract-text-webpack-plugin": "2.1.0", 48 | "file-loader": "^0.8.5", 49 | "html-loader": "^0.4.4", 50 | "html-webpack-plugin": "^2.15.0", 51 | "image-webpack-loader": "^2.0.0", 52 | "json-loader": "^0.5.4", 53 | "node-sass": "^3.13.1", 54 | "postcss-loader": "^0.11.1", 55 | "resolve-url-loader": "^1.6.0", 56 | "rimraf": "^2.5.4", 57 | "sass-loader": "^4.0.2", 58 | "style-loader": "^0.13.1", 59 | "superstatic": "^4.0.3", 60 | "to-string-loader": "^1.1.5", 61 | "ts-loader": "^0.8.1", 62 | "typescript": "^2.1.5", 63 | "url-loader": "^0.5.7", 64 | "webpack": "2.2.0", 65 | "webpack-dev-server": "^2.1.0-beta.10", 66 | "webpack-merge": "^0.14.0" 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /config/webpack.common.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 3 | var ExtractTextPlugin = require('extract-text-webpack-plugin'); 4 | var CopyWebpackPlugin = require('copy-webpack-plugin'); 5 | 6 | var helpers = require('./helpers'); 7 | 8 | //获取命令行下设置的环境变量 9 | var env = process.env.NODE_ENV; 10 | var isProd = env === 'prod'; 11 | 12 | module.exports = { 13 | entry: { 14 | 'polyfills': './src/polyfills.ts', 15 | 'vendor': './src/vendor.ts', 16 | 'main': './src/main.ts' 17 | }, 18 | //查找依赖文件路径 19 | resolve: { 20 | //指定后缀 查找文件的时候可以省略后缀 21 | //can ignore the ext when find the files 22 | extensions: ['.ts', '.js'] 23 | }, 24 | 25 | //指定各种loader 26 | //config some loader 27 | module: { 28 | //loader将各种资源文件最终处理为js文件 29 | //loader convert all the resource file to js 30 | loaders: [ 31 | { 32 | test: /\.ts$/, 33 | use: 34 | isProd ? 35 | ['@ngtools/webpack'] : 36 | [ 37 | '@angularclass/hmr-loader', 38 | 'angular2-template-loader', 39 | 'awesome-typescript-loader', 40 | 'angular2-router-loader' 41 | ] 42 | }, 43 | { 44 | test: /\.html$/, 45 | use: ['html-loader'] 46 | }, 47 | { 48 | test: /\.css$/, 49 | exclude: [ 50 | helpers.root('src', 'app') 51 | ], 52 | use: ExtractTextPlugin.extract({ 53 | fallback: 'style-loader', 54 | use: [ 55 | { 56 | loader: 'css-loader', 57 | options: { 58 | minimize: true 59 | } 60 | } 61 | ] 62 | }) 63 | }, 64 | { 65 | test: /\.css$/, 66 | include: [ 67 | helpers.root('src', 'app') 68 | ], 69 | use: [ 70 | { loader: 'to-string-loader' }, 71 | { loader: 'css-loader' } 72 | ] 73 | }, 74 | { 75 | test: /\.scss$/, 76 | exclude: [ 77 | helpers.root('src', 'app') 78 | ], 79 | use: ExtractTextPlugin.extract({ 80 | fallback: 'style-loader', 81 | use: [ 82 | { loader: 'css-loader' }, 83 | { loader: 'sass-loader' } 84 | ] 85 | }) 86 | }, 87 | { 88 | test: /\.scss$/, 89 | include: [ 90 | helpers.root('src', 'app') 91 | ], 92 | use: [ 93 | { loader: 'to-string-loader' }, 94 | { loader: 'css-loader' }, 95 | { loader: 'sass-loader' } 96 | ] 97 | }, 98 | { 99 | test: /\.(svg|woff|woff2|ttf|eot)$/, 100 | use: [ 101 | { 102 | loader: 'file-loader', 103 | options: { 104 | name: 'assets/iconfonts/[name].[hash].[ext]' 105 | } 106 | } 107 | ] 108 | }, 109 | { 110 | test: /\.(png|jpe?g|gif)$/, 111 | use: [ 112 | { 113 | loader: 'url-loader', 114 | options: { 115 | limit: 1024, 116 | name: 'assets/imgs/[name].[hash].[ext]' 117 | } 118 | } 119 | ] 120 | } 121 | ] 122 | }, 123 | 124 | plugins: [ 125 | new webpack.optimize.CommonsChunkPlugin({ 126 | name: ['main', 'vendor', 'polyfills'] 127 | }), 128 | 129 | !isProd ? new webpack.ContextReplacementPlugin( 130 | /angular(\\|\/)core(\\|\/)(esm(\\|\/)src|src)(\\|\/)linker/, 131 | __dirname 132 | ) : () => { }, 133 | 134 | //直接复制一些静态资源 135 | //copy some static resource 136 | new CopyWebpackPlugin([ 137 | { 138 | from: helpers.root('src', 'favicon.ico'), 139 | to: helpers.root('dist', 'favicon.ico') 140 | } 141 | ]), 142 | 143 | new webpack.LoaderOptionsPlugin({ 144 | options: { 145 | postcss: [ 146 | require('autoprefixer') 147 | ] 148 | } 149 | }), 150 | 151 | new HtmlWebpackPlugin({ 152 | template: 'src/index.html' 153 | }), 154 | 155 | //如果想引入jq,使用此代码 156 | //if you want to use jq,use this 157 | 158 | // new webpack.ProvidePlugin({ 159 | // $: "jquery", 160 | // jQuery: "jquery", 161 | // "window.jQuery": "jquery" 162 | // }) 163 | ] 164 | }; --------------------------------------------------------------------------------