Pull to refresh

CEF, ES6, Angular 2, WebPack 2 .Net Core десктопное приложение без серверной части

Reading time 6 min
Views 11K
Это продолжение статей:

CEF, ES6, Angular 2, TypeScript использование классов .Net Core. Создание кроссплатформенного GUI для .Net с помощью CEF
CEF, Angular 2 использование событий классов .Net Core

Основная идея этих статей — создание кроссплатформенных приложений на CEF с использованием Angular 2 и .Net Core. Чтобы отвязаться от сервера, используем свежий WebPack и настроим на локальное использование файлов.

Для начала создадим package.json.

Содержимое package.json
{
  "name": "helloapp",
  "version": "1.0.0",
  "scripts": {
    "start": "tsc && concurrently \"tsc -w\" \"lite-server\" ",
    "lite": "lite-server",
    "tsc": "tsc",
    "tsc:w": "tsc -w"
  },
  "dependencies": {
    "@angular/common": "~2.4.0",
    "@angular/compiler": "~2.4.0",
    "@angular/core": "~2.4.0",
    "@angular/forms": "~2.4.0",
    "@angular/http": "~2.4.0",
    "@angular/platform-browser": "~2.4.0",
    "@angular/platform-browser-dynamic": "~2.4.0",
    "@angular/router": "~3.4.0",
    "@angular/upgrade": "~2.4.0",
    "angular-in-memory-web-api": "~0.2.4",
    "babel-preset-es2015": "^6.22.0",
    "babel-preset-es2016": "^6.22.0",
    "babel-preset-react": "^6.23.0",
    "bootstrap": "^3.3.7",
    "core-js": "^2.4.1",
    "css-loader": "^0.26.1",
    "jquery": "^3.1.1",
    "postcss-loader": "^1.3.0",
    "raw-loader": "^0.5.1",
    "reflect-metadata": "^0.1.9",
    "rxjs": "^5.1.1",
    "sass-loader": "^6.0.0",
    "style-loader": "^0.13.1",
    "systemjs": "^0.20.7",
    "to-string-loader": "^1.1.5",
    "ts-loader": "^2.0.0",
    "typescript": "^2.1.6",
    "webpack": "^2.2.0",
    "webpack-fail-plugin": "^1.0.5",
    "webpack-notifier": "^1.5.0",
    "zone.js": "^0.7.7"
  },
  "devDependencies": {
    "@types/core-js": "^0.9.35",
    "@types/node": "^6.0.46",
    "babel-core": "6.23.1",
    "babel-eslint": "7.1.1",
    "babel-loader": "6.3.0",
    "babel-plugin-__coverage__": "^11.0.0",
    "babel-polyfill": "^6.0.0",
    "babel-preset-angular2": "^0.0.2",
    "babel-preset-es2015": "^6.22.0",
    "bootstrap-loader": "^2.0.0-beta.20",
    "bootstrap-sass": "^3.3.7",
    "chunk-manifest-webpack-plugin": "^1.0.0",
    "concurrently": "^3.1.0",
    "css-loader": "^0.26.1",
    "css-to-string-loader": "^0.1.2",
    "extract-text-webpack-plugin": "^2.0.0-rc.3",
    "file-loader": "^0.10.0",
    "html-webpack-plugin": "^2.28.0",
    "jquery": "^3.1.1",
    "lite-server": "^2.2.2",
    "node-sass": "^4.5.0",
    "resolve-url-loader": "^1.6.1",
    "sass-loader": "^6.0.0",
    "style-loader": "^0.13.1",
    "typescript": "^2.1.5",
    "url-loader": "^0.5.7"
  }
} 


Здесь собраны загрузчики, ссылки на необходимые файлы итд, которые были подобраны долгими исканиями.

Так же необходим tsconfig.json для компиляции TypeScript-файлов.

Содержимое tsconfig.json
{
  "compilerOptions": {
    "target": "es6",
    "module": "commonjs",
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": false,
    "noImplicitAny": true,
    "suppressImplicitAnyIndexErrors": true,
    "lib": [ "es6", "dom" ],
    "types": [ "node" ],
    "typeRoots": [
      "node_modules/@types"
    ]
  },
  "exclude": [
    "node_modules",
    "wwwroot",
    "**/*.spec.ts"
  ],

  "compileOnSave": true
}


Теперь мы можем создать на основании package.json директорию node_modules с помощью команды npm install из директории приложения.

Прежде чем вызывать WebPack, нужно создать несколько файлов polyfills.ts.

Содержимое polyfills.ts
import 'core-js/es6';
import 'core-js/es7/reflect';
require('zone.js/dist/zone');

if (process.env.ENV === 'production') {
  // Production
} else {
  // Development and test
  Error['stackTraceLimit'] = Infinity;
  require('zone.js/dist/long-stack-trace-zone');
}


Добавить в main.ts ссылки на Bootstap и JQuery:


import 'jquery';
import 'bootstrap-loader';
import 'bootstrap/dist/css/bootstrap.css';
import 'bootstrap/dist/css/bootstrap-theme.css';

Теперь нам доступны стили, glyphicons и тд. Теперь перейдем к самому главному, а именно webpack.config.js, на основании которого и будут собираться нужные нам файлы.

var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require("extract-text-webpack-plugin");

var helpers = require('./helpers');
var babelOptions = {
  "presets": [
    "react",
    [
      "es2015",
      {
        "modules": false
      }
    ],
    "es2016"
  ]
};

module.exports = {
  cache: true,
  entry: {
    polyfills: './app/polyfills.ts',
    main: './app/main.ts',
    vendor: [
      'babel-polyfill'
    ]
  },
  output: {
    path: './wwwroot',
    filename: './scripts/[name].js',
    chunkFilename: './scripts/[chunkhash].js',
    publicPath: './'
  },
  module: {
    rules: [{
      test: /\.ts(x?)$/,
      exclude: /node_modules/,
      include: /app/,
      use: [
        {
          loader: 'babel-loader',
          options: babelOptions
         
        },
        {
          loader: 'ts-loader'
        }
      ]
    }, {
      test: /\.js$/,
      exclude: /node_modules/,
      include: /app/,
      use: [
        {
          loader: 'babel-loader',
          options: babelOptions
        }
      ]
    },
      { test: /\.html$/, loader: 'raw-loader', exclude: [helpers.root('app/index.html')] },
      { test: /\.(png|jpg|jpeg|gif|svg)$/, loader: 'url-loader', query: { limit: 25000 } },
      { test: /\.css$/, loader: 'css-to-string-loader!css-loader' },
      { test: /\.scss$/, loaders: ['style', 'css', 'postcss', 'sass'] },
      { test: /\.(woff2?|ttf|eot|svg)$/, loader: 'url-loader?limit=10000' },
      { test: /bootstrap\/dist\/js\/umd\//, loader: 'imports?jQuery=jquery' }


    ]
  },
   resolve: {
       extensions: ['.ts', '.tsx', '.js','.css']
   },
   plugins: [
  // Workaround for angular/angular#11580
  
  new webpack.optimize.CommonsChunkPlugin({
      name: ['app', 'vendor', 'polyfills']
  }),

  new HtmlWebpackPlugin({
      template: 'app/index.html'

  }),
    new ExtractTextPlugin(
        {
            filename: 'styles.css',
            disable: false,
            allChunks: true
        }
),
new webpack.ProvidePlugin({
    jQuery: 'jquery',
    $: 'jquery',
    jquery: 'jquery'
})
   ]
};

Здесь собрано всё, чтобы использовать es6 и всё собиралось в несколько файлов в директории
'./wwwroot'. Теперь можно запустить webpack --config webpack.config.js, который и создаст нужные нам файлы.

Но нам придется подправить выходной index.html. Почему-то для:

<script type="text/javascript" src="././scripts/polyfills.js"></script>
<script type="text/javascript" src="././scripts/vendor.js">
</script><script type="text/javascript" src="././scripts/main.js"></script>

Добавляются лишние ./ — убрав ./, мы можем запустить index.html в любом браузере. Но нас интересует наш cefsimple.exe:

Укажем в адресе файла путь к index.html, например, d:\CEF\CefProgects\TestTypeScript\TestTypeScript\wwwroot\index.html

И Вуаля, мы работаем автономно, без Web-сервера. Если нужно подключиться к серверу, у нас есть все на .Net. Например, .Net Core, WCF и ODATA-клиенты.

Нужно добавить что я отказался от Routing в пользу NgSwitch

Так как в проект построен на использовании systemjs.config.js, то в нем нет поддержки require
который необходим для WebPack, что бы весь Html код интегрировался в js код.

Так как не нашел в TS условную компиляцию, для отладки необходимо закомментировать require

@Component({
    selector: 'nav-menu',
    template:require('./navmenu.component.html'),
    styles: [require('./navmenu.component.css')]

 //   templateUrl: 'app/navmenu/navmenu.component.html',
 //   styleUrls: ['app/navmenu/navmenu.component.css']
})


И раскомментировать


 //   templateUrl: 'app/navmenu/navmenu.component.html',
 //   styleUrls: ['app/navmenu/navmenu.component.css']


исходники и программы и инструкцию использования можно найти в предыдущих статьях в самом низу.
Tags:
Hubs:
+10
Comments 14
Comments Comments 14

Articles