2014年11月2日

JavaScript - 使用gulp來建置JS

這篇的來源,是從這裡來的,後來看到一半,發現已經有JS神人翻成中文了..Orz..但已經弄到一半,就還是留下來記錄一下…有興趣的朋友,可以直接去看中文版的,寫的很詳細也很棒喔!!

最近因為某些因素,也開始看看JS的建置方案,至於為什麼要建置,有很多的原因,舉例來說,我們希望把JS給min化,又或許是把多個JS給綑綁成一個,又或許是為了要測試;總之,近代的JS已經沒有以前那樣的單純,所以也需要個建置流程,來處理這些事情~

而除了今天要聊的gulp外,其餘還有grunt等方案,但小弟選的是gulp,其實也沒為什麼,就覺得他的設定過程滿好的XDDD,也容易理解,就選擇了gulp~

開始前,我們必須先透過npm進行安裝,不知道甚麼是npm的朋友,可以看一下這篇

裝完npm後,我們就可以透過npm install gulp -g進行第一次的全域安裝。

image

接下來,我們就進入我們要的專案底下,針對此專案,再安裝一次gulp。

image

完成之後,我們要持續的透過npm進行gulp的套件安裝;這邊有非常多的套件,因為神人那篇已經寫的很詳細了,小弟這邊就不多加敘述了。

  • gulp-uglify - 將JS醜化…( 就類似程式碼混淆器的功能 )
  • gulp-rename - 重新命名JS檔案
  • gulp-clean - 清除目標路徑
  • gulp-concat - 合併多個JS檔案
  • gulp-notify - 通知,完成後通知功能

image

接下來,我們要在專案下,建立一個gulpfile.js的檔案。

image

檔案的內容大致如下,簡單的說,前面是針對套件的載入,接下來使用pipe來讓套件一個一個的循序漸進的工作,而gulp.dest表示目標的路徑,這邊指的是當合併成main.js或是使用uglify後,要將js檔案放到哪個路徑…最後我們再使用gulp.start來啟動Task。

以下面的案例來說,我們先使用src讀取所有的js位置,並且透過concat合併成main.js並且輸出到assets/js的路徑下,接下來,我們將此檔案新建立一個.min的檔案並且混淆裡面內容後輸出到dist/assets/js底下,完成後,使用Scripts task complete來通知我們。

var gulp = require('gulp'),
    uglify = require('gulp-uglify'),
    rename = require('gulp-rename'),
    clean = require('gulp-clean'),
    concat = require('gulp-concat'),
    notify = require('gulp-notify');

gulp.task('scripts', function () {
    return gulp.src('src/scripts/**/*.js')
      .pipe(concat('main.js'))
      .pipe(gulp.dest('dist/assets/js'))
      .pipe(rename({ suffix: '.min' }))
      .pipe(uglify())
      .pipe(gulp.dest('dist/assets/js'))
      .pipe(notify({ message: 'Scripts task complete' }));
});

gulp.task('clean', function () {
    return gulp.src(['dist/assets/css', 'dist/assets/js', 'dist/assets/img'], { read: false })
      .pipe(clean());
});

// 預設任務
gulp.task('default', ['clean'], function () {
    gulp.start('scripts');
});

完成之後,我們只要進入指令模式,打入gulp,就可以呼叫建置。

image

基本上就先到這邊,其實原文的部分,還有包含CSS、瀏覽器自動更新等功能,如果迫不急待的朋友們,可以看看參考資料,那邊寫的非常詳細喔!~

未來小弟這篇,會再慢慢的補充上去。

另外,目前Visual Studio 2013已經有提供IDE的套件,至於未來的Visual Studio 2015,則會內建,未來也會持續更新。

參考資料

Visual Studio - 自動產生NuGet Package並移除舊版Package

延續前一篇,這篇要談的是一個小小的不方便與問題,畢竟人類的懶惰是沒有極限的。

如果大家有測是下來,可能就會發現如下圖的問題,是的,產生了非常多的nupkg檔案…畢竟每次增加一個版本,就會多兩個nupkg檔案如下圖;當然如果一開始少少的可能還好,但越來越多的時候,就會感覺很髒亂…,所以這篇,我們就來看看如何建立的過程中,順便移除舊版的Package。

image

那要怎麼做呢??,其實每次建立的時候,都是透過NuGet.targets來觸發動作,所以我們要增加一些小東西到NuGet.targets裡面去。

image

首先,我們要先在前面填入以下的Code,這邊我們定義了OutputPackages的內容,是nupkg的路徑。

<ItemGroup>
    <OutputPackages Include="$(TargetDir)*.nupkg" />
</ItemGroup>  

將此Code放到下圖的位置。

image

接下來,我們要定義一個CleanDependsOn的標籤,當條件成立的時候,就會執行此標籤裡面的內容。

<CleanDependsOn Condition="$(BuildPackage) == 'true'">
  $(CleanDependsOn);
  CleanPackages;
</CleanDependsOn>

我們要把此標籤放到底下的位置。

image

最後,這個內容到底要做甚麼事情哩,就是最後面這個標籤的內容了,也就是Delete Files,要刪除的檔案,就是我們一開始定義的路徑。

<Target Name="CleanPackages">
  <Delete Files="@(OutputPackages)"></Delete>
</Target>

我們把此標籤放到以下的位置。

image

完成之後,我們要使用重建的動作,如果只用建置,是沒辦法觸發的。

image

重建之後,我們就可以發現,原本的nupkg檔案全部都被砍掉了,只留下最新版喔!!

image

最後的最後,附上完整的NuGet.targets xml給大家參考~

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <OutputPackages Include="$(TargetDir)*.nupkg" />
  </ItemGroup>  
  <PropertyGroup>
        <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">$(MSBuildProjectDirectory)\..\</SolutionDir>

        <!-- Enable the restore command to run before builds -->
        <RestorePackages Condition="  '$(RestorePackages)' == '' ">false</RestorePackages>

        <!-- Property that enables building a package from a project -->
        <BuildPackage Condition=" '$(BuildPackage)' == '' ">false</BuildPackage>

        <!-- Determines if package restore consent is required to restore packages -->
        <RequireRestoreConsent Condition=" '$(RequireRestoreConsent)' != 'false' ">true</RequireRestoreConsent>

        <!-- Download NuGet.exe if it does not already exist -->
        <DownloadNuGetExe Condition=" '$(DownloadNuGetExe)' == '' ">false</DownloadNuGetExe>
    </PropertyGroup>

    <ItemGroup Condition=" '$(PackageSources)' == '' ">
        <!-- Package sources used to restore packages. By default, registered sources under %APPDATA%\NuGet\NuGet.Config will be used -->
        <!-- The official NuGet package source (https://www.nuget.org/api/v2/) will be excluded if package sources are specified and it does not appear in the list -->
        <!--
            <PackageSource Include="https://www.nuget.org/api/v2/" />
            <PackageSource Include="https://my-nuget-source/nuget/" />
        -->
    </ItemGroup>

    <PropertyGroup Condition=" '$(OS)' == 'Windows_NT'">
        <!-- Windows specific commands -->
        <NuGetToolsPath>$([System.IO.Path]::Combine($(SolutionDir), ".nuget"))</NuGetToolsPath>
    </PropertyGroup>

    <PropertyGroup Condition=" '$(OS)' != 'Windows_NT'">
        <!-- We need to launch nuget.exe with the mono command if we're not on windows -->
        <NuGetToolsPath>$(SolutionDir).nuget</NuGetToolsPath>
    </PropertyGroup>

    <PropertyGroup>
        <PackagesProjectConfig Condition=" '$(OS)' == 'Windows_NT'">$(MSBuildProjectDirectory)\packages.$(MSBuildProjectName.Replace(' ', '_')).config</PackagesProjectConfig>
        <PackagesProjectConfig Condition=" '$(OS)' != 'Windows_NT'">$(MSBuildProjectDirectory)\packages.$(MSBuildProjectName).config</PackagesProjectConfig>
    </PropertyGroup>

    <PropertyGroup>
      <PackagesConfig Condition="Exists('$(MSBuildProjectDirectory)\packages.config')">$(MSBuildProjectDirectory)\packages.config</PackagesConfig>
      <PackagesConfig Condition="Exists('$(PackagesProjectConfig)')">$(PackagesProjectConfig)</PackagesConfig>
    </PropertyGroup>
    
    <PropertyGroup>
        <!-- NuGet command -->
        <NuGetExePath Condition=" '$(NuGetExePath)' == '' ">$(NuGetToolsPath)\NuGet.exe</NuGetExePath>
        <PackageSources Condition=" $(PackageSources) == '' ">@(PackageSource)</PackageSources>

        <NuGetCommand Condition=" '$(OS)' == 'Windows_NT'">"$(NuGetExePath)"</NuGetCommand>
        <NuGetCommand Condition=" '$(OS)' != 'Windows_NT' ">mono --runtime=v4.0.30319 "$(NuGetExePath)"</NuGetCommand>

        <PackageOutputDir Condition="$(PackageOutputDir) == ''">$(TargetDir.Trim('\\'))</PackageOutputDir>

        <RequireConsentSwitch Condition=" $(RequireRestoreConsent) == 'true' ">-RequireConsent</RequireConsentSwitch>
        <NonInteractiveSwitch Condition=" '$(VisualStudioVersion)' != '' AND '$(OS)' == 'Windows_NT' ">-NonInteractive</NonInteractiveSwitch>

        <PaddedSolutionDir Condition=" '$(OS)' == 'Windows_NT'">"$(SolutionDir) "</PaddedSolutionDir>
        <PaddedSolutionDir Condition=" '$(OS)' != 'Windows_NT' ">"$(SolutionDir)"</PaddedSolutionDir>

        <!-- Commands -->
        <RestoreCommand>$(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)"  $(NonInteractiveSwitch) $(RequireConsentSwitch) -solutionDir $(PaddedSolutionDir)</RestoreCommand>
        <BuildCommand>$(NuGetCommand) pack "$(ProjectPath)" -Properties "Configuration=$(Configuration);Platform=$(Platform)" $(NonInteractiveSwitch) -OutputDirectory "$(PackageOutputDir)" -symbols</BuildCommand>

        <!-- We need to ensure packages are restored prior to assembly resolve -->
        <BuildDependsOn Condition="$(RestorePackages) == 'true'">
            RestorePackages;
            $(BuildDependsOn);
        </BuildDependsOn>

        <!-- Make the build depend on restore packages -->
        <BuildDependsOn Condition="$(BuildPackage) == 'true'">
            $(BuildDependsOn);
            BuildPackage;
        </BuildDependsOn>
      
        <CleanDependsOn Condition="$(BuildPackage) == 'true'">
          $(CleanDependsOn);
          CleanPackages;
        </CleanDependsOn>
    </PropertyGroup>

    <Target Name="CheckPrerequisites">
        <!-- Raise an error if we're unable to locate nuget.exe  -->
        <Error Condition="'$(DownloadNuGetExe)' != 'true' AND !Exists('$(NuGetExePath)')" Text="Unable to locate '$(NuGetExePath)'" />
        <!--
        Take advantage of MsBuild's build dependency tracking to make sure that we only ever download nuget.exe once.
        This effectively acts as a lock that makes sure that the download operation will only happen once and all
        parallel builds will have to wait for it to complete.
        -->
        <MsBuild Targets="_DownloadNuGet" Projects="$(MSBuildThisFileFullPath)" Properties="Configuration=NOT_IMPORTANT;DownloadNuGetExe=$(DownloadNuGetExe)" />
    </Target>

    <Target Name="_DownloadNuGet">
        <DownloadNuGet OutputFilename="$(NuGetExePath)" Condition=" '$(DownloadNuGetExe)' == 'true' AND !Exists('$(NuGetExePath)')" />
    </Target>

    <Target Name="RestorePackages" DependsOnTargets="CheckPrerequisites">        
        <Exec Command="$(RestoreCommand)"
              Condition="'$(OS)' != 'Windows_NT' And Exists('$(PackagesConfig)')" />

        <Exec Command="$(RestoreCommand)"
              LogStandardErrorAsError="true"
              Condition="'$(OS)' == 'Windows_NT' And Exists('$(PackagesConfig)')" />
    </Target>

    <Target Name="BuildPackage" DependsOnTargets="CheckPrerequisites">
        <Exec Command="$(BuildCommand)"
              Condition=" '$(OS)' != 'Windows_NT' " />

        <Exec Command="$(BuildCommand)"
              LogStandardErrorAsError="true"
              Condition=" '$(OS)' == 'Windows_NT' " />
    </Target>

    <Target Name="CleanPackages">
      <Delete Files="@(OutputPackages)"></Delete>
    </Target>

    <UsingTask TaskName="DownloadNuGet" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
        <ParameterGroup>
            <OutputFilename ParameterType="System.String" Required="true" />
        </ParameterGroup>
        <Task>
            <Reference Include="System.Core" />
            <Using Namespace="System" />
            <Using Namespace="System.IO" />
            <Using Namespace="System.Net" />
            <Using Namespace="Microsoft.Build.Framework" />
            <Using Namespace="Microsoft.Build.Utilities" />
            <Code Type="Fragment" Language="cs">
                <![CDATA[
                try {
                    OutputFilename = Path.GetFullPath(OutputFilename);

                    Log.LogMessage("Downloading latest version of NuGet.exe...");
                    WebClient webClient = new WebClient();
                    webClient.DownloadFile("https://www.nuget.org/nuget.exe", OutputFilename);

                    return true;
                }
                catch (Exception ex) {
                    Log.LogErrorFromException(ex);
                    return false;
                }
            ]]>
            </Code>
        </Task>
    </UsingTask>
</Project>

基本上,到這邊,就完成嚕!!

參考資料

Visual Studio - 使用Nuspec來自動產生NuGet Package

前一篇,我們使用MSBuild來達到Build的時候,自動產生NuGet Package,而當我們使用NuGet Package Explorer打開來看的時候,我們會發現Package metadata的資料也順便的幫我們填上了。

image

為什麼NuGet Package會知道填甚麼值呢?,那是因為它會自動抓AssemblyInfo.cs檔案,如下圖。

image

其中的對應表如下圖,我們可以改以下的對應表來產生不同內容的Package metadata,但要特別注意,AssemblyCulture必須保持為空值,不然會NuGet Package的產生,會有問題。

image

但實際上,AssemblyInfo還是不能涵蓋所有的Package metadata,更理想的狀況還是透過nuspec這個檔案來定義Package metadata;但如果自己要Key nuspec這個檔案也太辛苦了,所以我們可以從nupkg這個檔案,來解壓縮,找到nuspec。

( nupkg其實就是一個zip檔案,大家可以透過7-zip工具,或是直接把nupkg這個副檔名改成zip,就可以順利解壓縮了… )

image

之後,我們只需要把nuspec拷貝到專案的目錄底下去就可以了,但要特別注意,nuspec的檔案名稱,必須和專案的名稱相同喔!!

image

完成之後,重build一下,我們就可以發現,這次完全使用nuspec的內容了。

image

最後,要特別注意,因為我們希望建置NuGet Package的時候,他自動去抓取packages.config這個檔案,來解析相依的問題,所以別忘記把nuspec裡面的相依給移除掉喔。

image

也就是這行裡面的內容。

<dependencies>
  <dependency id="Newtonsoft.Json" version="6.0.6" />
</dependencies>

到這邊,就完成嚕!!~

參考資料

Visual Studio - 建置的時候自動產生NuGet Package

最近因為在寫一些Framwork給公司使用,雖然透過DLL直接給大家用也很方便,但畢竟這個時代,已經是NuGet的時代了,所以理想的情況下,還是放在NuGet上,比較方便 ( 當然,給公司用的Framework是自行架立的NuGet私服… )

而建立NuGet Package的過程中,我們可以透過NuGet的指令,或是NuGet Package Exploer,但NuGet指令要準備一堆東西…而NuGet Package Exploer則會遇到相依信套件要自己塞的窘境…而最最最理想的就是透過MSBuild的過程中,自動產生NuGet Package;這樣才符合懶人Sky的形象~~

所以去網路上找了一下,有些人有寫了一些套件,有些人有準備了一些專案,但還是看到這篇最符合小弟…( 原文連結在底下… ),所以就在這邊敘述一下過程。

首先,必須先啟用NuGet套件還原,是的,大家沒看錯,就是套件還原;這邊會使用套件還原的原因是因為,我們透過套件還原這個功能,可以幫我們把參數都給設定好,所以幾乎都不用做甚麼事情了… ( 懶人指數 + 1 )。

image

而套件還原功能開啟之後,還必須先隨便的使用NuGet下載任一套件,並且編輯,小弟這邊下載的是Json.Net。

為什麼要隨便下載一個套件勒!?,原因很簡單,因為你隨便下載一個套件之後,並且重Build,他才會自動的在專案檔下加入必要的參數。

加入的項目如下,基本上裡面的參數都是和套件還原有關的。

image

如下圖,我們可以看到,預設情況下,幫我們增加了NuGet的相關參數。

image

而實際上,到上面為止,都是處於套件還原的功能,所以我們要在專案檔這邊,加入BuildPackage的標籤,並且改為true;沒錯,就是這樣而已,這樣就可以了!!

image

這邊是原始的專案xml,有興趣的大家可以自由貼上。

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProjectGuid>{42ED14CC-0FAD-452C-966B-B484FE6BEDC2}</ProjectGuid>
    <OutputType>Library</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>ClassLibrary2</RootNamespace>
    <AssemblyName>ClassLibrary2</AssemblyName>
    <TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
    <FileAlignment>512</FileAlignment>
    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
    <RestorePackages>true</RestorePackages>
    <BuildPackage>true</BuildPackage>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>bin\Debug\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\Release\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
      <SpecificVersion>False</SpecificVersion>
      <HintPath>..\packages\Newtonsoft.Json.6.0.6\lib\net45\Newtonsoft.Json.dll</HintPath>
    </Reference>
    <Reference Include="System" />
    <Reference Include="System.Core" />
    <Reference Include="System.Xml.Linq" />
    <Reference Include="System.Data.DataSetExtensions" />
    <Reference Include="Microsoft.CSharp" />
    <Reference Include="System.Data" />
    <Reference Include="System.Xml" />
  </ItemGroup>
  <ItemGroup>
    <Compile Include="Class1.cs" />
    <Compile Include="Properties\AssemblyInfo.cs" />
  </ItemGroup>
  <ItemGroup>
    <None Include="packages.config" />
  </ItemGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
  <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
    <PropertyGroup>
      <ErrorText>此專案參照此電腦中缺少的  NuGet 套件。啟用「NuGet 套件還原」
      以便下載。如需詳細資訊,請參閱 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的檔案為 {0}。</ErrorText>
    </PropertyGroup>
    <Error Condition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))" />
  </Target>
  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
       Other similar extension points exist, see Microsoft.Common.targets.
  <Target Name="BeforeBuild">
  </Target>
  <Target Name="AfterBuild">
  </Target>
  -->
</Project>

當加入那行之後,我們重新Build後,就可以在bin底下的debug看到nupkg的檔案產生了!!其中symbols是提供偵錯用途的,裡面包含了source喔~

image

第一步驟就到這邊,就是那麼簡單~~

參考資料

2014年10月4日

紀錄文 - Windows 10 Technical Preview

年年有大事,這幾天最大的大事,大概就是Windows 10已經可以給大家去做測試與使用這件事吧,所以小弟的年度喇賽紀錄文,就又出現了!!

而這次除了Windows 10的出現,大家最好奇的應該就是9勒!!?..

而各種陰謀論就在網路上流傳了…例如,

  • 因為win 8.1 已經是等於9了,所以就跳過9…
  • 因為MS最近希望用One代表全新產品..例如OneDrive、XBox One、但因為Windows 1.0已經被大老闆Bill用過了,所以只能去到那個點,變成10…
  • 但小弟最喜歡的是這篇阿…因為檢查版號的偷懶,win 95 只檢查到9… ( 那98怎麼辦?.. )

但不管怎樣,反正就是稱為10嚕…

另外,這篇基本上就是個紀錄文,讓小弟未來可以回顧一下歷史上的今天,並不會談論有怎樣的新功能 ( 可能會談一點點啦… ),畢竟無論新功能或是一些細節,很多前輩都po過了,小弟就不多說嚕…

那有興趣下載的朋友,可以到這個網址去下載

基本上,小弟是把Windows 10 安裝到 Macbook的VM上( 使用 Parallels 10 ),有興趣的朋友可以參考這篇

安裝的過程中,就如同以前Win 8一樣,基本上不太可能會遇到甚麼問題;然後從Win 8開始,就可以綁定Microsoft Account,而這次我們也可以繼續使用Microsoft Account來登入~~

螢幕快照 2014-10-04 下午12.54.37

隨便就可以登入是非常可怕的事情,所以這邊會需要驗證,像小弟可能就使用手機簡訊來驗證,所以這邊要先輸入手機的最後四碼,然後他就會發簡訊來了~~

螢幕快照 2014-10-04 下午1.06.12

輸入簡訊上的號碼,就可以繼續,現在簡訊傳送還滿快的~

螢幕快照 2014-10-04 下午1.06.45

接下來,我們可以選擇要重新設定這個PC,或是用之前的設定;我覺得這個做得不錯,現在重灌電腦也越來越簡單了~

螢幕快照 2014-10-04 下午1.07.20

進來後,一眼望去的是新版的藍色畫面~~

螢幕快照 2014-10-04 下午1.10.48

然後下一秒,就瞬間變成Win 8.1的黃色了… ( 因為它會抓你之前電腦的設定…但我這邊想用藍色阿XDD );另外,大家期待的開始列回來了… ( 換小弟不習慣了..QQ ),而且開始列也整合了動態磚,一開始以為會很突兀,但實際上看了一下,覺得整合得還不錯~~也很方便使用。

螢幕快照 2014-10-04 下午1.11.24

到這邊,小弟又換回藍色桌布了XDD,其實如果可以的話,建議大家點一下桌面的使用說明,就可以輕鬆看到這次的Win 10有提供怎樣的新功能喔。

螢幕快照 2014-10-04 下午1.15.17

而在說明文件裡面,有一個小弟一直試驗不出來的功能,就是將開始功能表切回原本的Win 8的Style;後來決定直接進入控制台去做設定…設定方法如下;只要去Taskbar and Start Menu Properties裡面把"Use the Start menu instead the Start screen"取消勾選就可以了… ( 但小心,要重登電腦喔… )

螢幕快照 2014-10-04 下午1.35.13

完成,重新登入之後,就可以看到之前被大家砲轟,但小弟覺得滿好用的Win 8開始列XDD

螢幕快照 2014-10-04 下午1.33.43

當然,其他還有一些功能,例如類似Mac、Linux的Task View,可以幫我們Group工作項目等等新功能,大家有機會都可以玩玩看喔。

那喇賽文就先到這邊嚕~~

2014年9月15日

ASP.NET MVC - 真正的Web前端套件管理工具Bower

如果說…Scott Gu發表了Blog文章,那就代表了Azure又一堆東西要更新了…而如果是Scott Hanselman發表文章,那就代表著Microsoft這邊的Web開發又有新玩意了… ( 所以本質上,小弟本人滿討厭他們發文章的XDD )

而這次要探討的就是由Scott Hanselman發表的一篇文章,這篇文章的內文,大致上是講VS 2014將更加地符合現代前端的開發使用者,並且支援NPM、Bower、Gulp這些東西…

啥,完全沒聽過!?…其實沒聽過也是正常的,畢竟這些都屬於前端的玩意,Microsoft陣營的朋友可能都沒聽過,但對於JavaScript的神人,這些東西就等同於我們的NuGet一樣的平凡,而且每天都在用喔!!~~

所以今天來看一下Bower這個玩意…

Bower

是Twitter推出的,管理Web Package的一個工具,是的,他很像NuGet,我們可以透過Bower來進行套件的下載、相依性的管理;那大家的第一個疑問是…那和NuGet有啥兩樣!?…根據Scott的解釋是說…NuGet是Server端的套件管理工具,而Bower是前端的套件管理工具…那為什麼NuGet不能包含前端呢? ( 其實現在也有包含前端 ),Scott是說,因為目前已經有很多很棒的工具了…既然如此,那為何不用人家準備好的工具呢!??

好…基本上政治議題不是我們能關切與參與的…身為Developer,我們只要知道未來有怎樣的改變就好,所以…我們還是來看看Bower吧!!

image

首先,我們要安裝Bower之前…我們要先安裝npm…而npm則需要Node.js…所以大家可以翻翻小弟之前的文章,基本上Node.js很好安裝的;安裝完成之後,我們就擁有了npm,我們就可以輸入以下指令來安裝bower。

image

安裝完成之後,我們就可以隨處的安裝我們要的套件…,如果不知道有那些套件,可以從官網去做搜尋…

image

那接下來要怎樣安裝套件呢??大家可以參考官網的說明,基本上可以用install就可以來安裝套件,後面還可以接Git喔!!

image

那這邊,我有開了一個BowerTest的專案,我打算在這個空的專案底下裝上AngularJS;所以我就可以輸入。

bower install angular

但按下後,就遇到問題了…Orz…那是因為Bower下載需要透過Git…而且要設定PATH… ( 到這邊大家有沒有覺得其實Microsoft以前都幫我們處理得好好的,真的很幸福!? )

image

接下來,大家可以去網路上下載Git,然後再自行設定PATH,或是和小弟一樣,將很懶的個性發揮到極致…

小弟這邊的做法是去GitHub下載GitHub for Windows,這樣就有Git的指令了…但是雖然有Git的指令,但還是沒有設定PATH,而小弟也懶得去設定…所以小弟就直接打開Git Shell…

image

然後再一次,就可以了!!

image

基本上,bower會將下載來的東西放到bower_components底下…

image

大家如果看到上圖,應該會覺得,為啥AngularJS的東西那麼少…其實大家可以去AngularJS的GitHub看到,它們把所需要的東西都拆開了喔~~,如果想要一次下載全部版本,也可以去找angular-latest的這個版本。

image

自訂Package

接下來,我們可以自行定義Package,這邊指的Package有兩種涵義,一種是自己開發的Lib包成Package,放到Bower Server給大家下載;另外一種涵義則是把自行常用的東西包成一個.json檔案,到時候可以快速的一次下載;而這邊講的是後者喔。

首先,我們可以使用

bower init

這個指令,這個指令可以幫助我們建立bower.json檔案,到時候我們就可以把這個檔案Copy到其他專案快速重新下載Lib使用;過程中,會問一些小問題,後面會解釋到。

image

這邊列出了bower.json裡面用到的參數,那基本上也和建立bower.json時所問的問題差不多,相信大家比較一下大概就會清楚了,基本上,如果是自用,大概只需要填名稱,其他全部都選yes就可以了。

  • name (必填): 你的package名稱,如果未來要放到Bower Server上,公開給別人使用,則需要特別注意名稱。
  • version: 版本號。
  • main string or array: 你這個Package主要的檔案。
  • ignore array: 你希望Bower略過的檔案。
  • keywords array of string: 如果放到Bower Server上,關於你這個package的關鍵字,這有助於被容易尋找到。
  • dependencies hash: 相依的package,也可以標明版本。
  • devDependencies hash: 開發用的dependencies。
  • private boolean: 如果設為True,就可以防止被傳到Bower Server上去。

另外上面的選項還有what types of modules  does this package expose?,表示你使用哪一種JS的modules…例如 amd、es6等等…通常沒特別的話,按下enter,略過就可以。

set currently installed components as dependencies? 是否將目前安裝的套建設為依賴。
add commonly ignored files to ignore list?: 是否添加常用忽略的文件列表。

完成之後,就可以看到,再根目錄,出現了bower.json檔案嚕。

image

將新的套件加入到bower.json裡面

另外,我想應該不會有人想要每次加入一個新的套件,就init吧…所以官網有提供以下指令,可以讓大家再加入新套件的時候,順便寫到bower.json檔案裡面去。

image

這邊,我們就加入bootstrap~。

image

完成之後,我們就可以看到,相依了bootstrap了喔!~

image

還原

最後就是要進行還原,我們這邊開了一個新的WebApplication專案;接下來,我們把bower.json拷貝過來。

image

然後輸入bower install,就會立刻還原成功了喔!!!

image

有沒有很簡單勒??…當然,官方還有一些API,大家如果有興趣的話,可以再去看一看喔!!

參考資料

2014年9月14日

TechDays 2014 - 使用 Azure Web Site 打造雲端網站 - 全方位的網站管理、佈署與監控技巧

今年的年度聚會TechDays 2014又結束了,每次TechDays結束,就意味著暑假也結束了,今年夏天又要過了,然後,到了年底,就是趕案子加班的日子了…抖抖…

今年TechDays講的主題是"使用 Azure Web Site 打造雲端網站 - 全方位的網站管理、佈署與監控技巧",那相信有很多朋友在等著錄影檔,所以這邊就先不多說廢話,先供奉上錄影檔在說嚕。

Demo影片下載

PhotoWall的Source Code

接下來,就是Sky的碎碎念與幕後花絮了,有興趣的朋友,再繼續往下看下去吧=v=

準備

如果有拿到光碟的朋友,大概也會看到下面這張圖,這張圖其實是小弟我在準備講這堂課前的手稿…( 嗯..字醜不是重點.. )

2014-09-08 23.07.04

當初規劃這堂課程的時候,心中也有很多疑問,到底要端出怎樣的菜色給大家??

其實這是一個沒有答案的問題,來上課的朋友,有些人可能完全沒碰過Azure,有些人在實務上已經用的很深入,而有些人搞不好連Azure是甚麼都不知道… ( 讓我想到那個徽章…Azure是甚麼?能吃嗎??XDD );那我在Demo的時候,到底是要把一個一個的功能去做展現,還是要把東西串起來,又或者是要從頭開始介紹Azure ??

後來小弟我決定的是,將Azure串起來進行Demo,而不是一個功能一個功能去作呈現;會選擇這個的原因,是因為希望讓台下的朋友們,感受到的是一個整個Azure的整合與應用,而非單獨一個功能一個功能。

所以後來敲定的流程,就是從一個專案的開始,從建立專案,到佈署、開發、監控與各種關於Azure Web Site的功能與使用…

當然,這也造成後續整個講課過程delay …

影片

其實如果可以,小弟我也百萬個不願意用影片Demo QQ…

如果有朋友Follow小弟的FB…其實就可以發現在TechDays前的一兩個月,就已經聽到小弟在FB狂抱怨New Portal… ( 但畢竟人家是Preview…也怨不得人家阿QQ… )

在過程中,第一個遇到的問題就是慢…New Portal的UX真的非常慢…接下來,就是不穩定因素太多…小弟我在實驗過程中所遇到的問題其實滿多的,而且也沒辦法避開… ( 常常這次ok,下次失敗… ),所以最後也只能決定放棄直接Demo,改用影片的方式…畢竟在過程中,實在是沒辦法讓大家看到一直不斷失敗的Demo阿…

所以最終決定的就是錄影片了…

中秋節

不知道大家有沒有發現,TechDays固定是星期2、3、4…然後一定是中秋節過後的那個禮拜!! ( 其實小弟也是今年聽前輩說才發現… ),而今年中秋節整整的三天放假,就努力的在錄那些影片…是的,整整三天都在錄…沒去烤啥肉 ( 電腦是快燒起來了… ),也沒看到月亮 ( 到是有看到檯燈… ),那為什麼短短的幾支影片,就需要耗掉三天!?;其實應該反過來說…就是因為會需要耗掉三天,所以才不敢當場Demo阿!!!!~

但不管怎樣,其實我覺得三天放假都在搞這些,也都還好,畢竟3天對小弟來說是72小時,但如果沒準備好,當天現場出狀況,如果以500人計算,70分鐘乘上500,就不是短短的72小時了;我相信每個講師的心中想法都是一樣的,大家都背負著台下每個人的每分每秒,所以大家通常會抱怨的都是系統不穩XDD,而不會抱怨說沒辦法放假,無法過中秋=V=。

縮小架構

其實在真實上,錄出來的影片 ( 錄失敗的就不說了 ) ,成功的影片不只上面那些,大概整整快多了兩倍…當初初期的規劃,其實還有建置測試的環境;但計算時間的時候,就發現時間不夠用了,所以就把測是那塊的環境建置,全部給砍了…

PhotoWall

這個事情是發生在錄影片之前,也是畫架構圖之前臨時決定的應用程式;其實當初並沒有特別要準備一個應用程式,比較將重心放於Azure的功能面上,後來看到Ruddy師傅、黃忠成老師都準備了一些很棒的Demo,才決定做一個PhotoWall,而後來也將整個Demo串起來…

而當初預期最好的狀況是,Live建置環境,然後Live Coding,最後讓會場的大家可以直接將照片上傳到Azure上去…

image

但後來還是沒辦法成真,其中一個原因就如前面說的…New Portal有一些問題、其次就是時間上的不允許…

所以到最後,就演變成這個範例先準備好,而以這個範例為核心,用類似回顧的方式,來介紹Azure的服務,而Code的撰寫部分,就只能犧牲掉了…

投影片

雖然說砍掉了很多東西,但其實到最後,投影片也累積了97張…如果以現場70min來說,97張投影片,都快要可以變成動畫了…Orz…所以在講課前,其實就已經預測到會延誤下課了= =+。

講課過程

過程中,會緊張嗎?…其實也不是第一次講課了…而且在台上往下看,也真的只能看到第一排XDD,其餘幾乎都只看到探照燈..Orz…所以其實完全不會緊張…

但這次講課的過程中,卻有一些沒處理好的事情,舉例來說,發光碟這件事情…其實當初應該是要把光碟先放在講台前…後來忘記了…Orz…所以在傳遞的過程中也遇到一些小問題…

其次;過程中幾乎都是座著講…其實我自己是比較喜歡站著的,但就如前面說的,在看完投影片後,大概也可以預期一定會延誤下課,所以後來就變成專注於趕課…所以也沒辦法站起來好好講QQ…所以其實嚴格說起來,這次的備課,是有一點缺失的~~想給的東西太多,沒有再好好精簡的結果阿!!~

其次就是影片的撥放,到後期,我也感受到,整個影片其實是很跳動,又很快的…所以這部份也在這邊和學員說聲抱歉>"<…

下圖是剛開放進場的狀況…

2014-09-09 16.38.41

當然,在這過程中,還是要感謝上圖坐在第一排,幫忙當跑退的好友饅頭兄,真的很感謝他義無反顧地幫小弟我發光碟>"<~

後續

目前還沒拿到大家的意見回饋,但除了上面提到的缺失外,影片、Code的提供,其實也可以早一點放到投影片上面給大家拍…這樣大家就不用等著這篇文章的出現…

此外,以前有老師說過,台上一分鐘,台下十年功,其實真的一點也不錯,雖然只有短短的70min,但我相信不管是哪個老師,從頭地收集資料,然後篩選出適合大家的課程內容,再經過不知道幾次的review,調整;其實到上台前一分鐘,大家可能都還在調整投影片,為的就是能讓各位朋友有更多的收穫~~也為的是台下朋友聽完那滿足的表情~~

當然,很多東西小弟也沒做到盡善盡美,也有很多不好之處,這也請大家多多包涵了。

那最後,還是要感謝當天來聽課的朋友,與背後支持的朋友,謝謝大家!~明年TechDays見嚕~