Visual Studio 2017, .NET Core a nový formát projektů

Tomáš Herceg       13.12.2016       C#, Visual Studio, ASP.NET/IIS, .NET       16245 zobrazení

V červenci 2016 byla uvedena první ostrá verze nové .NET Frameworku, a sice .NET Core 1.0. Tato platforma je revoluční téměř po všech myslitelných stránkách.

Zaprvé je open source a hostována na GitHubu. Do vývoje, opravy bugů a různých výkonnostních optimalizací se zapojila celá řada lidí z komunity, a v issues jsou mnohdy k vidění velmi plodné a zajímavé diskuse. Microsoftu je tak více vidět pod pokličku a dá se lépe odtušit, kam bude vývoj směřovat.

Zadruhé je multiplatformní a již od začátku byla navržena tak, aby ji bylo možno provozovat na Linuxu a Macu. Podporuje i ARM a malá zařízení, například Raspberry PI Zero, které stojí 5 dolarů.

A do třetice ani téměř půl roku od jejího uvedení k ní zatím neexistuje ostrá verze toolingu a neustále se mění podoba projektových souborů a toho, jak se aplikace kompilují.

 

Pokud jste si již s .NET Core hráli, jistě jste narazili na spoustu různých problémů, divných chybových hlášek. Všechny tyto problémy jsou způsobeny neustále se měnícím toolingem a změnou formátu projektových souborů. V tomto článku si stručně zrekapitulujeme, k jakým změnám zde došlo a jak poznat starý formát projektů od nového.

 

Bezbřehý optimismus a JSON

Klasické projektové soubory (ty s příponou CSPROJ) v .NET Frameworku měly několik nepříjemných neduhů. Asi největším problémem bylo, že obsahovaly seznam všech C# souborů, které jsou zahrnuté v projektu. V případě, že člověk na projektu pracoval sám, to nepředstavovalo víceméně žádný problém, důvodů k ruční editaci CSPROJ souboru nebylo nikdy příliš mnoho, takže ani to, že je soubor dlouhý ničemu nevadilo.

V týmovém prostředí se ale jednalo o častou komplikaci a častý zdroj konfliktů v případě, že více lidí z týmu přidalo do projektu nějaké soubory. V mnoha případech se stávalo, že nově přidané soubory sice v source control systému byly, ale do projektu je bylo třeba přidat ručně. Nehledě na to, že přidání souboru automaticky v historii source control vygenerovalo i změnu projektového souboru, což zbytečně zapleveluje historii.

Po vzoru Node.js se Microosft rozhodnul nahradit korporátní a nepopulární XML formát dnes moderním JSONem. Objevil se tak soubor project.json, který celkem elegantním způsobem obsahoval všechny podstatné informace. Zároveň zavedl konvenci, že vše, co je ve složce projektu, je automaticky zahrnuto, a pouze věci, které jsou z kompilace vyloučeny, se zapisují do projektového souboru, a navíc ještě typicky pomocí wildcardu.

Větší integrace se dočkal také Nuget. V klasickém .NET Frameworku je Nuget jen takové chytřejší makro pro Visual Studio – instalace balíčku je jen automatizace činností, které byste museli dělat sami – stažení knihovny a případně dalších souborů, přidání reference do projektu a případně další úpravy CSPROJ nebo konfiguračních souborů projektu. Samotný build systém o existenci Nugetu v zásadě vůbec neví a u referencované knihovny nedokáže rozlišit, jestli se jedná o Nuget balíček, nebo o obyčejný DLL soubor, který někdo přidal ručně.

V novém projektovém formátu je integrace s Nugetem daleko užší a v souboru project.json se uvádí přímo názvy a verze balíčků, které mají být v projektu zahrnuty. Dokonce i reference projektů mezi sebou se tváří jako kdybyste instalovali Nuget balíček – v zásadě platí idea (převzatá z Node.js), že každý projekt je balíček, který se akorát nemusí nikam publikovat.

{
  "dependencies": {
    "Microsoft.NETCore.App": {
      "version": "1.0.1",
      "type": "platform"
    },
    "Microsoft.AspNetCore.Diagnostics": "1.0.0",
    "Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
    "Microsoft.AspNetCore.Server.Kestrel": "1.0.0",
    "Microsoft.Extensions.Logging.Console": "1.0.0",
    "Microsoft.AspNetCore.StaticFiles": "1.0.0",

    "DotVVM": "1.1.0-alpha",
    "DotVVM.AspNetCore": "1.1.0-alpha",

    "Microsoft.EntityFrameworkCore": "1.0.1",
    "Microsoft.EntityFrameworkCore.SqlServer": "1.0.1",
    "Microsoft.EntityFrameworkCore.Tools": {
      "version": "1.0.0-preview2-final",
      "type": "build"
    },

    "Microsoft.AspNetCore.Identity": "1.0.0",
    "Microsoft.AspNetCore.Identity.EntityFrameworkCore": "1.0.0"
  },

  "tools": {
    "Microsoft.AspNetCore.Server.IISIntegration.Tools": "1.0.0-preview2-final",
    "Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final"
  },

  "frameworks": {
    "netcoreapp1.0": {
      "imports": [
        "dotnet5.6",
        "portable-net45+win8"
      ]
    },
"net461": {} } }

Sekce dependencies obsahuje seznam Nuget balíčků, které se mají před kompilací do projektu nainstalovat.

Dále je zde sekce tools, která definuje rozšíření do command line utility dotnet, která se dá použít například ke spuštění webové aplikace pomocí serveru Kestrel (stačí spustit v projektovém adresáři příkaz dotnet web), pro tvorbu migrací v novém Entity Framework Core (dotnet ef …) atd.

Sekce frameworks specifikuje, pro které platformy se má aplikace kompilovat. Vzhledem k tomu, že mnoho knihoven chce podporovat jak nový, tak starý .NET, je možné zde uvést více frameworků, a kompilátor poté vytvoří dvě verze – jednu pro .NET Core, druhou pro plný .NET 4.6.1. Každý framework může ještě uvnitř obsahovast sekci dependencies, kam by se uvedly balíčky specifické pro danou verzi .NET Frameworku.

 

Vystřízlivění

Po krátkém období euforie s formátem JSON nastalo vystřízlivění, během kterého se ukázalo, že by bylo nereálné předělat vše, co dnes běží na MSBuildu (protože CSPROJ je jen skript pro MSBuild). Proto bylo oznámeno, že se project.json ruší a vracíme se k zpátky CSPROJ, byť ve změněné podobě, která řeší hlavní neduhy.

Současně s uvedením Visual Studia 2017 RC se tedy přešlo na nový formát projektů, který má též příponu CSPROJ. Nejzásadnější změnou je, že Nuget balíčky se referencují pomocí elementu PackageReference, což je zlepšení oproti původnímu stavu, kde v souboru packages.config byl uveden seznam balíčků, a v projektovém souboru se balíčky přidávaly jako normální reference na DLL.

Současně se v projektovém souboru objevily wildcardové importy souborů s příponou CS, což nás konečně zbaví nutnosti řešit merge konflikty pokaždé, kdy více lidí přidá soubor. Navíc Visual Studio nyní sleduje změny ve filesystému a nové soubory přidá automaticky bez nutnosti projekt reloadovat.

<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" />
  <PropertyGroup>
    <AssemblyTitle>DotVVM</AssemblyTitle>
    <TargetFrameworks>netstandard1.6;net451</TargetFrameworks>
  </PropertyGroup>
  <ItemGroup>
    <Compile Include="**\*.cs" Exclude="node_modules;bin\**;obj\**;**\*.xproj;packages\**" />
    <EmbeddedResource Include="**\*.resx" Exclude="bin\**;obj\**;**\*.xproj;packages\**" />
  </ItemGroup>
  <ItemGroup>
    <Compile Remove="node_modules\**" />
    <EmbeddedResource Remove="node_modules\**" />
  </ItemGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.NET.Sdk">
      <Version>1.0.0-alpha-20161104-2</Version>
      <PrivateAssets>All</PrivateAssets>
    </PackageReference>
    <PackageReference Include="NETStandard.Library">
      <Version>1.6.0</Version>
    </PackageReference>
	...
    <Reference Include="System" />
    <Reference Include="Microsoft.CSharp" />
    <Reference Include="System.ComponentModel.DataAnnotations" />
  </ItemGroup>
  <PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard1.6' ">
    <DefineConstants>$(DefineConstants);DotNetCore</DefineConstants>
  </PropertyGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

Projekty též podporují kompilaci pro více frameworků zároveň (element TargetFrameworks) a pomocí klasických podmínek v MSBuildu je možné specifikovat reference nebo jiná nastavení pro konkrétní platformy.

Pokud ve Visual Studio 2017 RC otevřete projekt se souborem project.json, Visual Studio jej automaticky zupgraduje, což je příjemné. Nefunguje to stoprocentně, nicméně drtivou většinu projektů nám to zkonvertovalo správně. Migraci lze také provést spuštěním dotnet migrate z příkazového řádku.

 

Úkrok stranou

Včera (12. 12. 2016) Microsoft uvedl update pro Visual Studio 2017 RC, které mění formát CSPROJ souboru. Výhodou je, že projektový soubor je mnohem stručnější. Nevýhodou (a to dost zásadní) je, že pokud jste project.json upgradovali na CSPROJ, neexistuje oficiální upgrade cesta z nového CSPROJ formátu na tento nejnovější. Více informací lze najít v Release Notes.

Vzhledem k tomu, že DotVVM už jsme na CSPROJ zupgradovali, nezbylo mi než si napsat tool, který migraci na nejnovější formát usnadní. Najdete jej na GitHubu.

 

 

Doufejme, že Microsoft už moc dalších změn v toolingu dělat nebude, a že jej co nejdříve konečně dotáhne do finální verze. Je pochopitelné, že investují hodně úsilí do toho, aby tooling byl perfektní, a přestože se mi myšlenka project.jsonu líbila, nový formát CSPROJ souboru je též použitelný, řeší všechny problémy, a nebude nutné kvůli němu předělávat tisíce nástrojů, které spoléhají na MSBuild. Současná situace je dost nešťastná, protože ať hledáte jakýkoliv návod, najdete nejčastěji verzi pro project.json. Pro nové projektové soubory moc návodů zatím není.

 

hodnocení článku

0       Hodnotit mohou jen registrované uživatelé.

 

 

 

Nový příspěvek

 

Příspěvky zaslané pod tento článek se neobjeví hned, ale až po schválení administrátorem.

Tak hrozné Node.js není

@Marian Benčat Už vůbec nezmiňuji to, že Node.js tvoří složky až do úrovně 10 milionu /node_modules/.../node_modules .. takže to na windows ani pak nejde smazat a musi se mazat rekurzivně.

Dlouho jsem nevěděl proč ty adresáře nejdou jednoduše smazat :) Je to peklo. Ale tak hrozné to s Node.js jinak není, jak píšete dále.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Bohužel souhlasit nemohu :-/ Problém není v samotném Node.js, ani v NPM. Problém je, že vývojáři nemají takové zkušenosti, jako jinde..

teď se na mě snese ohromný hate, ale je to pravda. Víte, já jsem byl (a díky bohu stále jsem) více jak 6 let Backend vývojář (C++/ C#) a jsem zvyklý, že nainstaluju balík a mohu se spolehnout na to, že funguje, a že i když ho nainstaluju za půl roku, tak to bude i za půl roku fungovat.

Jenže u NPM máte většinu dependencies jako range, většinou ^, tedy ve většině případů minor a patch verze. Tedy - u patch verze NESMÍ být žádná breaking change a změny by měly být tak minimální, že se nevejde žádná chyba.

Opak je pravdou. Vidím to téměř každou hodinu, hlavně bohužel na tom, že buildíme pravidelně na CI frontendové aplikace pomocí Webpacku atd.

Ve 12:00 to funguje, ve 13:00 ne. Chyba je samozřejmě v 35. řádce callstacku, protože v balíčku A->B->C->D->E->F->G-> TADY vydal autor Patch verzi, která obsahuje tolik breaking changes..

Jeden příklad za všechny.. v NPM je balík "isArray", tento balík obsahuje toto:

return toString.call(arr) == '[object Array]';

Ten balíček má 1 000 000 stáhnutí denně..je na něm závislých 180 jiných balíků a na něm je závislých dále 11 000 balíků, včetně těch nejpoužívanějších.

Tedy jde o velmi sofistikovanou knihovnu, která nahradí psaní:

  if (arr.toString() == '[object Array]')

za 1 dependency navíc, 20souborů na disku a

  if (isArray(arr))

pominu zde efektivitu implementace.. a nebudu zde ani bláhově věřit, že každý inteligentní člověk si tuto funkci napíše asi za 10sec sám.

A takhle je to v JS se vším.. Oni se skrývají za to, že je to "hiding of complexity", tedy.. sice je to teď jedna řádka, ale za rok to může být řádek 100.. A já se ptám "opravdu"? Je to naprosto stejná hloupost jako premature optimalizace - ať už v kódu, nebo na velikosti přenesených kB, což je něco, nad čím Frontendisté naprosto onanují a aby ušetřili 2kB na přenesených datech a 2 requesty.. tak si:

1) Napíšou nebo stáhnou webpack loader

2) Přenastaví celý webpack

3) předělají hardcoded věci na require() v celým projektu

4) Nechají to encodnout do base64 a tak zobrazí obrázky.

Well done.

Pokud si autor usmyslí, že ten balík smaže, přestane 11 000 balíků fungovat, protoze nepujdou ani nainstalovat a ani zbuildit. Vše je postavené na tak vratkých základech..

Viz tento příklad:

http://qz.com/646467/how-one-programmer-...

Pokud chcete vyvíjet v ES6 a využijete Babelu, nainstaluje se vám na disk 47 000 souborů, slovy "čtyřicet sedm tisíc".

Já už absolutně chápu, proč lidé jako Altair šli radši točit porno, než aby v tom vyvíjeli.

Jestli .NET upustí u balíků od zbuilděných DLL a pujde na tento styl JS, kdy balík = zdrojáky, které jsou závislé na dalších 40ti balíčkách (dalších zdrojácích) tak potěš pánbůh a já asi začnu hubnout, aby o mé filmy byl zájem ;-)

Pokud vás ani toto nepřesvědčilo, tak dám z minulého týdne muj asi nejooblibenejsi priklad, na který jsem bohužel přišel sám..

Jistě znáte moment.js, defakto je to jediný způsob, jak si při práci s datumem a casem v Javascriptu nevystřelit mozek z hlavy. Je na něm závislý bez nadsázky celý internet..

Asi před měsícem nebo kdy vydali novou MINOR verzi moment.js a je tam asi 8 hojně využívaných funkcí, které mají v sobě závažný bug - bohužel,.. ono to tam nespadne.. jen to počítá absolutní nesmysly:

moment({m: 420}) vracelo dříve správně 7 hodin - ostatně, tak jak je to popsané v dokumentaci.

Po té nové minor verzi to vrací 42 minut.

Já nevím jak ostatní, ale prý se Node.js používá v NASA. Nechtěl bych vidět ten výraz lidí v Houstonu, až jim Lunatic 50 zabočí doprava o pár hodin dříve :-)))

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Node se opravdu v NASA používá, stejně jako Python, Haskell apod. Ale ona taková aplikace jen většinou agreguje data a zobrazuje je v dashboardu -- což už je zase normální frontend. Jinak, víte že jste mne docela přesvědčil? .)

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Jojo, to s tím, že řídí nějaký satelit, nebo lunární modul byla legrace :-)

Kdybych to asi nemusel používat každý den, tak to prostě může kdokoliv považovat za flame.. ale vzhledem k tomu, že s tím opravdu denně bojuji už nějakou dlouhou dobu, tak prostě opravdu jsem z toho smutný (kulantně řečeno) a tak podávám svoje zkušenosti s tímto "ekosystémem" opravdu bez obalu a mohu jen doufat, že toto samé zlo nedorazí do MS světa.

Hezký den :-)

nahlásit spamnahlásit spam 0 odpovědětodpovědět

inspirace Node.JS? to snad radsi ani ne..

Já se toho popravdu naprosto děsím...

Jako chápu, že .NET vývojáři netrpí takovým autismem jako Node.js vývojáři...

Ale co mě na celém Node.js a NPM neskutečným způsobem vytáčí jsou především tyto dvě věci:

1) JS vývojáři naperou do každého balíčku 1 řádku kódu

2) JS vývojáři si myslí že modulární architektura = vše v jednom souboru (můžeme to nejlépe vidět na PHP3 - chci říct React.js)

3) NPM a 95% balíčku mají v sobě Range verzí, která je 100% závislá na tom, že všichni vědí co je Semver a jak verzovat... jenže se ukazuje, že to absolutně nefunguje.. každý vývojář napere do patch / minor verze tolik bugu a HLAVNĚ breaking changes, že 1. den buildíme a 2. den nebuildime, protoze v balíčku, který je dependence u balíčku, který je dependencí balíčku, který používáme v balíčku.,..(never ending story) vydal novou verzi a jelikož děláme clean build, tak se natáhne nová verze a je to celá v h...

Prostě,. Frontendový svět táhne do pekel a já jen doufám, že si to Microsoft uvědomí v čas a nepujde stejnou cestou, protože je to jen jeden velký PAIN.

CO mě děsí asi ještě více je, že ať nainstaluju jen blbej babel, mam 47 000 souboru ve slozcd a pri instalaci se mi vypíše 1000 řádek warningu o možném DDOS utoku, o peer dependency problemech atd.

Už vůbec nezmiňuji to, že Node.js tvoří složky až do úrovně 10 milionu /node_modules/.../node_modules .. takže to na windows ani pak nejde smazat a musi se mazat rekurzivně.

Tím celým chci říct,.. ať si to Microsoft udělá jak chce, halvně ať to nedělá podle Nodeu, prtoože to je ten absolutně největší odpad, co se v posledních 100 letech v IT objevil.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Pěkné

Takovýchto článků z praxe si vysoce cením.

Díky za ně.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.

Nyní zakládáte pod článkem nové diskusní vlákno.
Pokud chcete reagovat na jiný příspěvek, klikněte na tlačítko "Odpovědět" u některého diskusního příspěvku.

Nyní odpovídáte na příspěvek pod článkem. Nebo chcete raději založit nové vlákno?

 

  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

Příspěvky zaslané pod tento článek se neobjeví hned, ale až po schválení administrátorem.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:
Heslo:

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback