【问题标题】:Setup a web project with elm in visual studio 2015在 Visual Studio 2015 中使用 elm 设置 Web 项目
【发布时间】:2024-04-27 15:25:01
【问题描述】:

如何在visual studio 2015 中设置带有elm 的Web 项目?

我们开始了一个新项目,我们需要它在visual studio 中用于持续集成和构建部署到某个服务器。

我的问题是我没有找到elm 项目模板,而且我最近才听说过 elm,所以这对我来说也是新事物。

任何帮助将不胜感激。

【问题讨论】:

    标签: visual-studio-2015 elm project-template


    【解决方案1】:

    我们提出了一个结构,其中我们的 UI 是一个单独的项目,完全用 Elm 编写,而后端是 ASP.NET。 整个过程都在一个 Visual Studio 解决方案中,可以在 TeamCity 中使用 VS2015 或 MSBuild 进行编译。

    我们使用 VS Code 来开发 UI。我不知道任何 Visual Studio 对 Elm 的支持。

    这是包含在 UI 项目中的项目文件 (YourUI.csproj):

    <?xml version="1.0" encoding="utf-8"?>
    <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
      <PropertyGroup>
        <ProjectGuid>{B9D43DC2-6337-4605-BBE2-7C7C765EDC20}</ProjectGuid>
        <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
      </PropertyGroup>
      <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
        <BuildTask>build:dev</BuildTask>
      </PropertyGroup>
      <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
        <BuildTask>build:release</BuildTask>
      </PropertyGroup>
      <Target Name="Build">
        <Exec Command="echo Executing npm install..." Condition="!Exists('$(ProjectDir)node_modules')" />
        <Exec Command="npm install" Condition="!Exists('$(ProjectDir)node_modules')" />     
        <Exec Command="echo Building the UI using GULP..." />
        <Exec Command="echo ---------------------------------------------" />
        <Exec Command="gulp $(BuildTask)" />
        <Exec Command="echo ---------------------------------------------" />
      </Target>
      <Target Name="Clean">
        <Exec Command="gulp clean:all" />
      </Target>
      <Target Name="Rebuild" DependsOnTargets="Clean;Build" />
      <ItemGroup>
        <None Include="readme.md" />
      </ItemGroup>
    </Project>
    

    如您所见,在后台我们使用npmgulp 来完成实际工作。 我们 gulp 文件中的重要部分(包括 Elm CSS 生成和 WebPack 捆绑):

    gulp.task('elm-init', function (cb) {
        return gulp.src('src/*.elm')
            .pipe(elm())
            .pipe(gulp.dest('JS/generated'));
    });
    
    gulp.task('elm:dev', ['elm-init'], function (cb) {
        return gulp.src('src/main.elm')
            .pipe(elm.bundle('elm.js'), {
                debug: true
            })
            .pipe(gulp.dest('JS/generated'));
    });
    gulp.task('elm:release', ['elm-init'], function (cb) {
        return gulp.src('src/main.elm')
            .pipe(elm.bundle('elm.js'))
            .pipe(gulp.dest('JS/generated'));
    });
    
    bundle = function () {
        return gulp.src('JS/index.js')
            .pipe(webpackGulp({
                output: {
                    filename: 'Ui.js',
                }
            }))
            .pipe(gulp.dest('build/'));
    }
    gulp.task('bundle:dev', [/*project spcific things, */ 'elm:dev'], bundle);
    gulp.task('bundle:release', [/*project spcific things, */ 'elm:release'], bundle);
    
    gulp.task('css', function (cb) {
        mkdirp('build/css', function (err) {
            if (err) console.error(err)
        });
    
        exec(path.resolve('./node_modules/.bin/elm-css')
            + ' --pathToMake ./node_modules/.bin/elm-make'
            + ' src/Stylesheets.elm',
            function (err, stdout, stderr) {
                console.log(stdout);
                console.log(stderr);
                cb(err);
            });
    });
    
    gulp.task('build:dev', function (cb) {
        runSequence('clean:dev', 'bundle:dev', 'css');
    });
    

    ASP.NET 项目文件包含以下BeforeBuild 指令:

      <Target Name="BeforeBuild">
        <MSBuild 
            Projects="..\YourUI\YourUI.csproj"
            Condition="'$(Configuration)'=='Release' OR !(Exists('$(SolutionDir)YourUI\build\Ui.js') AND Exists('$(SolutionDir)YourUI\build\css'))" 
            Targets="Build" />
        <Exec Command="echo Creating UI resources for $(Configuration)..." />
        <!-- Delete old links -->
        <Delete Files="$(ProjectDir)Scripts\Ui.js" />
        <Delete Files="$(ProjectDir)Scripts\Ui.min.js" />
        <RemoveDir Directories="$(ProjectDir)Content\Ui" />
        <!---->
        <!---->
        <!-- DEBUG build-->
        <!---->
        <Exec Condition=" '$(Configuration)'=='Debug' " Command="mklink $(ProjectDir)Scripts\Ui.js $(SolutionDir)YourUI\build\Ui.js" />
        <Exec Condition=" '$(Configuration)'=='Debug' " Command="mklink /d $(ProjectDir)Content\Ui $(SolutionDir)YourUI\build\css" />
        <!---->
        <!---->
        <!-- RELEASE build-->
        <!---->
        <ItemGroup Condition=" '$(Configuration)'!='Debug' ">
          <ElmApp Include="$(SolutionDir)YourUI\build\Ui.min.js" />
          <ElmStyles Include="$(SolutionDir)YourUI\build\css\*.css" />
        </ItemGroup>
        <Copy Condition=" '$(Configuration)'!='Debug' " SourceFiles="@(ElmApp)" DestinationFolder="$(ProjectDir)Scripts" />
        <Copy Condition=" '$(Configuration)'!='Debug' " SourceFiles="@(ElmStyles)" DestinationFolder="$(ProjectDir)Content\Ui" />
      </Target>
      <!-- Include the new files as content -->
      <ItemGroup Condition=" '$(Configuration)'=='Debug' ">
        <Content Include="Scripts\Ui.js" />
        <Content Include="Content\Ui\*.css" />
      </ItemGroup>
      <ItemGroup Condition=" '$(Configuration)'!='Debug' ">
        <Content Include="Scripts\Ui.min.js" />
        <Content Include="Content\Ui\*.css" />
      </ItemGroup>
    

    【讨论】:

    • 这在 GitHub 上是否可用,或者您可以在 GitHub 中发布示例解决方案吗?很想试试这个。
    【解决方案2】:

    从技术上讲,它不需要在 Visual Studio 2015 中成为持续集成或开发的一部分。对于编辑,使用 Visual Studio Code(或其他编辑器,如 Sublime、Vim、Atom 等)可能会减少摩擦。

    但是,如果您仍希望它与 Visual Studio 2015 生态系统相关联,您将需要使用 Task Runner 集成。您已经在 IDE 中内置了 grunt and gulp 任务运行器。您可以创建一个 gulp 任务并使用 gulp-elm 自动监视和编译您的 Elm 代码。

    就我个人而言,我是 Elm 开发的 Webpack 的粉丝。加上一个额外的Visual Studio 2015 plugin for Webpack task runners,你应该能够很好地把它绑在一起。 (警告:我没有亲自尝试过这种组合,但它看起来很合法)

    【讨论】:

    • 是否可以创建一个任务来编译并在浏览器中启动页面?我已经设置了编译、监视和连接的任务,但是当我启动任务时,我无法在浏览器中启动它 (*.com/questions/40914056/…)
    • 我已经通过gulp-connect-multigulp-open 两个选项提供了关于该问题的答案