深入理解Deno是如何借助PowerShell进行安装脚本

528 阅读5分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

Deno Deno Deno...满天飞,趁昨个儿摸鱼安装了把环境,今天回顾下Deno安装史,并深入看看它是如何使用powershell安装的。

什么是Deno

如果你熟悉Node.js,那么Deno就像Node.js一样,同样属于服务端JavaScript运行时。但是它很多方面都得到了改善,比如下面一些功能列表:

  • Deno 基于最新的 JavaScript 语言;
  • Deno 具有覆盖面广泛的标准库;
  • Deno 以 TypeScript 为核心,配以更多独特的方式从而带来了巨大的优势,其中包括一流的 TypeScript 支持(Deno 自动编译 TypeScript 而无需你单独编译);
  • Deno 大力拥抱 ES 模块标准;
  • Deno 没有包管理器;
  • Deno 具有一流的 await 语法支持;
  • Deno 内置测试工具;
  • Deno 旨在尽可能地与浏览器兼容,例如通过提供内置对象 fetch 和全局 window 对象。

了解完Deno,下面就安装个环境试试。

安装最新版

使用Shell:

curl -fsSL https://x.deno.js.cn/install.sh | sh

使用PowerShell:

iwr https://x.deno.js.cn/install.ps1 -useb | iex

安装某个特定版本

使用 Shell:

curl -fsSL https://x.deno.js.cn/install.sh | sh -s v1.0.0

使用 PowerShell:

$v="1.0.0"; iwr https://x.deno.js.cn/install.ps1 -useb | iex

环境变量

  • DENO_INSTALL - Deno 的安装目录。默认为 $HOME/.deno。Deno 可执行文件将安装在 $DENO_INSTALL/bin 目录。 安装成功后将对所有用户有效:

使用 Shell ( /usr/local):

curl -fsSL https://x.deno.js.cn/install.sh | sudo DENO_INSTALL=/usr/local sh

使用 PowerShell (C:\Program Files\deno):

# 使用管理员模式运行:
$env:DENO_INSTALL = "C:\Program Files\deno"
iwr https://x.deno.js.cn/install.ps1 -useb | iex

至此便能顺利完成Deno的安装,对应那几行执行的命令是如何执行的,你是否感到好奇呢?下面一起看看那几行脚本都干了什么事情!

PowerShell脚本分析

我采用的是PowerShell命令进行的安装,这里就采用此案例进行解析。

1. 安装命令行分析
iwr https://x.deno.js.cn/install.ps1 -useb | iex

执行内容是:通过iwr命令,获取x.deno.js.cn/install.ps1…

别名

这里的iwrInvoke-WebRequest的别名 ,用途是获取http web请求访问内容,-useb是执行网络请求的参数。iwr命令还存在更强大的功能,比如:添加header,指定Method,将获取的content输出到指定文件等等。(如感兴趣,可自行学习)

Invoke-WebRequest语法:

Parameter Set: Default
Invoke-WebRequest [-Uri] <Uri> [-Body <Object> ] [-Certificate <X509Certificate> ] [-CertificateThumbprint <String> ] [-ContentType <String> ] [-Credential <PSCredential> ] [-DisableKeepAlive] [-Headers <IDictionary> ] [-InFile <String> ] [-MaximumRedirection <Int32> ] [-Method <WebRequestMethod> {Default | Get | Head | Post | Put | Delete | Trace | Options | Merge | Patch} ] [-OutFile <String> ] [-PassThru] [-Proxy <Uri> ] [-ProxyCredential <PSCredential> ] [-ProxyUseDefaultCredentials] [-SessionVariable <String> ] [-TimeoutSec <Int32> ] [-TransferEncoding <String> {chunked | compress | deflate | gzip | identity} ] [-UseBasicParsing] [-UseDefaultCredentials] [-UserAgent <String> ] [-WebSession <WebRequestSession> ] [ <CommonParameters>]

当然windows powershell还存在很多可以快速使用的别名,别名引用和使用标准范式是等效的。安装脚本里存在的别名还有:`````iexInvoke-Expression的别名,表达的是执行表达式。如果你想查看所有的别名,可以在控制台输入命令:alias`,输出截图如图下

管道“|”

PowerShell的管道都是基于对象,这点不同于传统的Cmd的管道是基于文本。此安装脚本属于面向对象的管道,每个命令的末尾可以使用新的命令对上个命令的结果做进一步处理,除非管道是以输出命令结束的。

加深管道理解,再看个命令行:

PS> ls | Sort-Object -Descending Name | Select-Object Name,Length,LastWriteTime | ConvertTo-Html | Out-File ls.html

命令行执行的内容是:首先列出当前目录下的目录和文件,然后根据文件名降序排列,再投影文件名,文件大小,文件的修改时间,转换成Html格式,输出到当前目录的ls.html。

至此完整解析了安装脚本命令行,下面看看具体的脚本内容是啥样的。

2. 安装脚本分析

首先看下完整的脚本,我们再分析内部的PowerShell语法执行流程。

#!/usr/bin/env pwsh
# Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
# TODO(everyone): Keep this script simple and easily auditable.
# 自定义变量
$ErrorActionPreference = 'Stop'
# $v,执行安装脚本指定的版本号
if ($v) {
  $Version = "${v}"
}

if ($args.Length -eq 1) {
  $Version = $args.Get(0)
}
# $env:DENO_INSTALL 取环境变量指定的值(安装路径)
$DenoInstall = $env:DENO_INSTALL
$BinDir = if ($DenoInstall) {
  "$DenoInstall\bin"
} else {
  "$Home.deno\bin"
}

$DenoZip = "$BinDir\deno.zip"
$DenoExe = "$BinDir\deno.exe"
$Target = 'x86_64-pc-windows-msvc'

# GitHub requires TLS 1.2
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
# 命令行未指令版本,则默认从请求获取最新版本的值
if (!$Version) {
  $Version = (Invoke-WebRequest 'https://dl.deno.land/release-latest.txt' -UseBasicParsing).Content.Trim()
}

$Version = $Version.Replace("v","")
# 根据版本情况,取deno脚本的zip文件地址
if ($Version -match "1.[0-6]+.[0-9]+") {
  $DenoUri = "https://cdn.jsdelivr.net/gh/justjavac/deno_releases/$Version/deno-${Target}.zip"
} else {
  $DenoUri = "https://dl.deno.land/release/v${Version}/deno-${Target}.zip"
}
# 判断$BinDir是否存在,不存在则创建空目录
if (!(Test-Path $BinDir)) {
  New-Item $BinDir -ItemType Directory | Out-Null
}
# 获取网络请求获取$DenoUri的内容,并输出到$DenoZip
Invoke-WebRequest $DenoUri -OutFile $DenoZip -UseBasicParsing
# 将DenoZip压缩文件提取到BindDir目录
if (Get-Command Expand-Archive -ErrorAction SilentlyContinue) {
	# Expand-Archive 命令:将压缩文件提取到指定的目录,-Force:不用征求用户意见
  Expand-Archive $DenoZip -Destination $BinDir -Force
} else {
  if (Test-Path $DenoExe) {
    Remove-Item $DenoExe
  }
  # Add-Type cmdlet允许您在PowerShell会话中定义Microsoft.NET核心类。
  # 然后可以使用New Object cmdlet实例化对象,并像使用任何.NET核心对象一样使用这些对象。
  # 如果向PowerShell配置文件中添加add Type命令,则该类在所有PowerShell会话中都可用。
  Add-Type -AssemblyName System.IO.Compression.FileSystem
  [IO.Compression.ZipFile]::ExtractToDirectory($DenoZip, $BinDir)
}
# 移除zip压缩文件
Remove-Item $DenoZip
# 当前用户 () 关联的环境变量保留的 Windows 操作系统注册表项
$User = [EnvironmentVariableTarget]::User
# 获取系统的环境变量Path
$Path = [Environment]::GetEnvironmentVariable('Path', $User)
# 系统环境变量Path不存在deno/bin,则添加上
if (!(";$Path;".ToLower() -like "*;$BinDir;*".ToLower())) {
  [Environment]::SetEnvironmentVariable('Path', "$Path;$BinDir", $User)
  $Env:Path += ";$BinDir"
}
# 控制台输出
Write-Output "Deno 安装成功"

整体大体流程是这样的:

  1. 执行Deno安装脚本
  2. 取安装脚本命令行的版本号 $v ,未配置,则默认从请求获取最新版本号;
  3. 从环境变量 $env:DENO_INSTALL 取Deno安装路径,若存在,则使用 $env:DENO_INSTALL``\binbin 安装路径 $BinDir ; 若未指定,则使用默认路径:$Home.deno\bin 。并且当 $BinDir 不存在,则创建空目录。
  4. 根据版本号 $Version 规则,指定Deno脚本的下载地址:$DenoUri,从资源地址上可以看出是个zip压缩文件。
  5. 执行 Invoke-WebRequest 命令,将 $DenoUri 的请求内容输出到位置:$DenoZip
  6. $DenoZip 压缩文件提取到$BinDir,并删除 $DenoZip 压缩文件
  7. 取当前用户关联的环境变量保留的 Windows 操作系统注册表项,并获取变量 Path 所包含的所有值;判断 $BinDir 是否注册到 Path ,未注册,则自动注册。
  8. 控制台输出:Deno 安装成功,

最后,验证下是否安装成功,控制台输入命令并执行:deno help

总结

至此学习了Deno的安装流程,以及PowerShell是如何进行脚本安装,这里涉及大量的PowerShell语法,文章里面只是简单说明,若存在不准确的地方,欢迎指正。后续时间安排上,将安排波PowerShell基本编程入门学习文章。