The iOS Developer’s Introduction to Vapor (3)

The iOS Developer’s Introduction to Vapor (3)

Server-side Swift has been around for a couple of years and as time goes by the maturity of putting Swift on the server grows. With this talk, I will give an introduction to one of the most popular server-side Swift frameworks called Vapor, which recently released a new major version. I will talk a bit about how I ended up doing server-side Swift development after working with iOS for years and I’ll look at the potential synergy between Vapor and iOS. This talk requires no prior knowledge to server-side Swift.

9993186221ec65f6f10db0dc9cff7c07?s=128

Steffen D. Sommer

October 04, 2018
Tweet

Transcript

  1. 2.

    " Head of Vapor Development at Nodes Full time Vapor

    developer since January 2017 Background in iOS development ~50 customer projects and ~40 packages @steffendsommer
  2. 3.
  3. 5.
  4. 6.

    A web framework built in Swift Official support for SQLite,

    MySQL, PostgreSQL and Redis Built on top of SwiftNIO
  5. 7.
  6. 10.

    1.0 Sep, 2016 2.0 May, 2017 3.0 April, 2018 0.1

    Jan, 2016 Timeline borrowed from Tanner Nelson
  7. 12.

    import Vapor let app = try Application() let router =

    try app.make(Router.self) router.get("hello") { req in return "Hello, world." } try app.run()
  8. 13.

    Strong, safe and modern language Fast and has a low

    memory footprint (aka. ) Tech awesomeness ♻ Potential synergy between iOS and Vapor
  9. 14.

    ♻ Models ⚠ Errors Frameworks used in both places Endpoints

    & Environments Business logic Styling Test code (e.g. mocks) ✅ Validation ☂ A framework that wraps the endpoints
  10. 17.

  11. 28.

    ?

  12. 30.

    Create a new post Show all published posts, sorted by

    a publish date Show details of a single post
  13. 34.
  14. 37.
  15. 38.

    // swift-tools-version:4.2 import PackageDescription let package = Package( name: "ServerSideSwiftWork",

    dependencies: [ // A server-side Swift web framework. .package(url: "https://github.com/vapor/vapor.git", from: "3.0.0"), // Swift ORM (queries, models, relations, etc) built on SQLite 3. .package(url: "https://github.com/vapor/fluent-sqlite.git", from: "3.0.0"), // Template engine .package(url: "https://github.com/vapor/leaf.git", from: "3.0.1"), ], targets: [ .target(name: "App", dependencies: ["Leaf", "FluentSQLite", "Vapor"]), .target(name: "Run", dependencies: ["App"]), .testTarget(name: "AppTests", dependencies: ["App"]) ] )
  16. 39.
  17. 40.

    final class Work: Codable { public var id: Int? public

    var company: String public var location: String public var title: String public var description: String public var externalUrl: String public var publishedAt: Date? public init( company: String, location: String, title: String, description: String, externalUrl: String, publishedAt: Date? = nil ) { self.company = company self.location = location self.title = title self.description = description self.externalUrl = externalUrl self.publishedAt = publishedAt } }
  18. 42.
  19. 43.

    func create(_ req: Request) throws -> Future<Work> { return try

    req .content .decode(Work.self) .save(on: req) }
  20. 44.

    func index(_ req: Request) throws -> Future<[Work]> { return Work

    .query(on: req) .filter(\.publishedAt != nil) .sort(\.publishedAt, .descending) .all() }
  21. 45.

    struct ViewData: Codable { let work: [Work] } func renderIndex(_

    req: Request) throws -> Future<View> { return Work .query(on: req) .filter(\.publishedAt != nil) .sort(\.publishedAt, .descending) .all() .flatMap { items in try req.view().render("index", ViewData(work: items)) } }
  22. 46.
  23. 47.
  24. 49.
  25. 50.

    public func routes(_ router: Router) throws { let workController =

    WorkController() router.get("api/work", use: workController.index) router.get("api/work", Work.parameter, use: workController.show) router.post("api/work", use: workController.create) router.get("work", use: workController.renderIndex) }
  26. 51.

  27. 52.

    public func configure(_ config: inout Config, _ env: inout Environment,

    _ services: inout Services) throws { /// Register providers first try services.register(FluentSQLiteProvider()) try services.register(LeafProvider()) config.prefer(LeafRenderer.self, for: ViewRenderer.self) /// Register routes to the router let router = EngineRouter.default() try routes(router) services.register(router, as: Router.self) /// Register middleware var middlewares = MiddlewareConfig() middlewares.use(ErrorMiddleware.self) services.register(middlewares) // Configure a SQLite database let sqlite = try SQLiteDatabase(storage: .memory) /// Register the configured SQLite database to the database config. var databases = DatabasesConfig() databases.add(database: sqlite, as: .sqlite) services.register(databases) /// Configure migrations var migrations = MigrationConfig() migrations.add(model: Work.self, database: .sqlite) services.register(migrations) }
  28. 53.
  29. 56.

    let sqlite = try SQLiteDatabase(storage: .memory) var databases = DatabasesConfig()

    databases.add(database: sqlite, as: .sqlite) services.register(databases)
  30. 58.
  31. 59.
  32. 60.
  33. 61.
  34. 64.

  35. 65.
  36. 68.

    Multiple regions and cloud providers Custom docker templates ♻ Internal

    DNS setup Build pipeline ✏ Releases and rollback Public API Database IP Built-in Git server Commands in separate replicas ⚙ Loadbalancer configuration More statistics All features in the dashboard Config updates without redeployment And much more… Version 2
  37. 70.

    https://docs.vapor.codes https://discord.gg/vapor Tim Condon - Getting Started with Server Side

    Swift and Vapor (Codemobile 2018) ? https://www.serversideswift.work https://www.serversideswift.info
  38. 71.
  39. 72.