前端指南 前端指南
指南
资源
  • 刷力扣 (opens new window)
  • 手写题 (opens new window)
  • 归档
  • 分类
  • 标签
  • 关于我
  • 关于本站
GitHub (opens new window)

Seognil LC

略懂点前端
指南
资源
  • 刷力扣 (opens new window)
  • 手写题 (opens new window)
  • 归档
  • 分类
  • 标签
  • 关于我
  • 关于本站
GitHub (opens new window)
  • 运行 JavaScript 代码的十几种方式

    • 目录
      • 浏览器
        • HTML script 标签
        • DevTools
      • 命令行
        • VS Code 编辑器
          • Code Runner
          • Quokka
        • 工程化
          • CLI
          • Webpack
          • Parcel
          • Rollup、Microbundle
        • 编译器(在线预览)
          • Babel - Try it out
          • TypeScript Playground
          • AST Explorer
          • JavaScript Visualizer
        • 在线编辑器
          • 其他
            • jsconsole
            • Console Importer
            • carbon
            • dwitter.net
        • note
        • frontend
        • javascript
        Seognil LC
        2020-04-21
        目录

        运行 JavaScript 代码的十几种方式

        运行 JavaScript 代码的十几种方式

        有人可能会想:JS 就是 JS,在浏览器里用的,哪有什么这么多运行方式,你别来什么用 Chrome 打开、用 Firefox 打开,就算两种啊。

        其实我不是要标题党或是博人眼球。现实中确实有各种各样的需求和使用场景,导致了需要使用不同的工具来运行编写好的代码。
        (而且 JS 现在的作用也不仅仅局限于做网页。)

        本文按顺序列举一些我所知道和用过的工具,
        从学习,到做项目,到深入 JS 语言,等等…
        来看看 JS 代码写好之后究竟怎么能发挥它作用。

        那么在以后看到别人的代码片段时,就能知道怎样自己调试从中学习。
        或者需要向他人提问时,如何展示自己的代码。

        工欲善其事,必先利其器。如果是初学者,首先要了解的肯定是怎么运行代码、以及如何更快地调试代码。

        对于初学者来说,我推荐优先了解和使用以下工具,可以显著地提高代码学习效率:

        • DevTools
        • node
        • Parcel
        • Code Runner
        • Quokka

        如果是有经验的开发者,我也分享了一些不错的实用工具。

        希望你看完这篇文章,能够更好地运用 JS 这门编程语言~

        # 目录

        本文目录,大致的分类:

        • 开发
          • 浏览器
            • HTML script 标签
            • DevTools
          • 命令行 (node、babel-node、ts-node)
          • VS Code 编辑器
            • Code Runner
            • Quokka
          • 工程化
            • CLI
            • Webpack、Parcel
            • Rollup、Microbundle
        • 编译器(在线预览)
          • Babel
          • TypeScript
          • AST Explorer
          • JavaScript Visualizer
        • 在线编辑器 (JS Bin、CodePen、StackBlitz、CodeSandbox)
        • 其他
          • jsconsole
          • Console Importer
          • carbon
          • dwitter.net

        # 浏览器

        # HTML script 标签

        这可能是所有前端开发者最先学习到的概念(无论通过什么学习途径)。

        当然,现代前端开发的样貌早已天翻地覆,我们有一大堆自动化工具可以利用(后文会提及),可能不再需要手写 HTML 了。有些较新的学习教程可能已经没有花太多篇幅在这方面。

        但是如果是做网页项目,那么最终还是会回到这里(即使是通过工具自动完成)。

        我们追根溯源,看看如何通过网页的方式运行 JS。

        <!-- index.html -->
        <html>
          <head></head>
          <body>
            <script src="https://code.jquery.com/jquery-3.5.0.min.js"></script>
            <script>
              console.log('Hello from HTML');
            </script>
            <script src="index.js"></script>
          </body>
        </html>
        
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        // index.js
        console.log('Hello from .js');
        
        1
        2

        这个 Demo 中,我写了三个 script 标签, 他们的作用分别是:

        • CDN 加载一个第三方库

        看到了熟悉的 jquery。如果你是最近几年新入行的选手,即使不再需要 jQuery,那你可能也听说过它的大名~ 事实上,即使是使用当前世代的框架进行开发,为了一些原因(比如网络性能?)可能也会继续用这种方式,

        比方说 Vue 官方文档 (opens new window) 中提及的:

        <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
        
        1

        浏览器读取 URL 相应的 JS 文件并执行。

        需要注意的是,加载远程文件的过程是同步(阻塞)的。
        (除非注明 async、defer 等属性,这里不表)

        • 直接在 script 标签内写 JS 代码
        <script>
          console.log('Hello from HTML');
        </script>
        
        1
        2
        3

        我们自己的业务代码,可以直接写在标签内部,这是 HTML 规范所定义的另一种方式,
        浏览器将标签内部的字符串识别为 JS 代码并运行。

        • 加载我们自己的 JS 文件
        <script src="index.js"></script>
        
        1
        // index.js
        console.log('Hello from .js');
        
        1
        2

        直接在 HTML 中写 JS 可能无法很好的分割代码,所以一般会写在单独的 JS 文件中。
        类似于加载第三方库,只不过通过我们自己设定的资源路径。

        扩展阅读:

        • “Hello World!”示例 - MDN (opens new window)
        • script 标签 (opens new window)

        # DevTools

        另一种和浏览器密切相关的方式是:

        在浏览器的 DevTools(调试界面)的 Console 板块中,也能直接输入 JS 代码并执行。
        这能够方便地对当前应用进行调试,而不用直接修改源码。

        chrome devtools get started console

        DevTools 还有断点、性能、内存分析等更多和调试有关的功能,在框架开发或大型应用开发时很有用。

        详情可以通过 Chrome 的官方文档进行系统地学习:

        在 Chrome DevTools 中调试 JavaScript(入门) (opens new window)

        # 命令行

        前端开发发展至今,除了 JS 的业务代码,还需要很多编译和处理工具。源码在发布到网页前,需要提前在本地进行处理。这就需要借助专门的工具了。

        也就是 Node.js (opens new window),它是一个 JS 运行环境,它包含了和 Chrome 浏览器一样的 V8 JS 引擎 (opens new window)。

        除了 Node 本身,还有支持扩展语法和新特性的 @babel/node (opens new window) 和 TS node (opens new window)。它们相当于 Babel (opens new window) + Node、TypeScript (opens new window) + Node,能够做更多的事情。

        他们都是运行在命令行中的工具,调用方式如下:

        node ./index.js
        babel-node ./index.js
        ts-node ./index.js
        
        1
        2
        3
        // index.js
        console.log('Hello World!');
        
        1
        2

        ts-node(特性的支持需要 tsconfig (opens new window) 配合)

        ts-node ./index.ts
        
        1
        // index.ts
        import util from './lib.ts';
        util.log('Hello world');
        
        //  lib.ts
        export default {
          log: console.log,
        };
        
        1
        2
        3
        4
        5
        6
        7
        8

        也可以直接启动 node,在命令行内编写代码。

        $ node
        Welcome to Node.js v13.13.0.
        Type ".help" for more information.
        
        > const hello = () => console.log('Hello World!');
        
        > hello()
        Hello World!
        
        1
        2
        3
        4
        5
        6
        7
        8

        JS 本身是一个图灵完备的语言,能够完成很多复杂的工作。比如代码压缩、图片处理等等这些前端开发的常见技术需求。

        那么我们有了更高效的无界面运行时之后,工程就可以更好地展开了,JS 编程领域也随之蓬勃发展。

        甚至,连服务器、爬虫、机器学习,这些“跨界”的工作也开始出现。

        # VS Code 编辑器

        VS Code (opens new window) 是一个 流行 (opens new window) 的代码编辑器。

        值得一提的是,它本身就是一个用 TypeScript 编写、并运行在 Node 之上的大型应用。(所以它甚至有机会运行在网页上)

        它不仅能够编写代码,还内置了调用终端(命令行)的功能。编写完 JS 代码,就可以直接使用 node 系列工具进行调试。
        甚至,还能像浏览器一样 进行断点调试和代码追踪 (opens new window)。

        Breakpoints

        除了这些自带的功能,我平时会使用两个额外的插件来增强调试的体验。

        # Code Runner

        Code Runner (opens new window)

        支持快捷键和截选运行

        code runner usage

        # Quokka

        Quokka (opens new window)

        支持自动运行,直接预览结果,省去频繁的手动操作。

        quokka vs code intro

        # 工程化

        在学会了 JS 的基本语法和特性之后,代码的真正价值要发挥在工作中:网页应用、命令行工具、或是混合开发的 APP 等等。这些是项目,比文档教程中的 Demo 代码规模更大、更有现实意义。

        借助上文提及的基本工具,或许能对局部代码文件进行运行和调试。
        但运行整个应用,则需要借助更多的工具。

        于是,我们碰到了现代前端开发中的一个重要概念:构建(Building、Bundling)。

        支持扩展语法(TypeScript、JSX)、增量编译整个项目、即时预览,这些都是提升开发效率和体验的重要组成部分。

        提前介绍一个网站 Create App - your tool for starting a new webpack or Parcel project (opens new window),它针对下面即将介绍的 Webpack 和 Parcel,为常见的业务提供了基本的配置集。

        # CLI

        • Create React App (opens new window)
        • Vue CLI (opens new window)
        • Angular CLI (opens new window)
        • Polymer CLI (opens new window)
        • UmiJS (opens new window)
        • Omi (opens new window)

        对于现代前端框架来说,CLI 几乎是标配了。

        所谓 CLI,也就是 Command Line Interface,命令行界面。

        有的甚至还带有图形界面(下图为 Vue CLI)

        vue cli gui

        开箱即用,不需要关心编译原理和配置,直接进入业务开发环节。极大地减少了开发成本。

        然后调用封装好的命令即可一键编译运行。

        一般这些命令的常见形式有:

        npm run start
        npm run serve
        npm run dev
        npm run build
        
        1
        2
        3
        4

        顺便一提,现代框架发展至今,除了 CLI,它们甚至还有自己专门的 DevTools。比浏览器自带的 DevTools 更有针对性,调试框架项目更加方便。

        • React Developer Tools (opens new window)
        • Vue.js devtools (opens new window)

        # Webpack

        What is Webpack

        • Webpack (opens new window)
        • Webpack 中文文档 (opens new window)

        虽然 CLI 很方便,但是对于更复杂的应用或是定制的业务需求。
        可能还是要不断调整配置,甚至手动编写额外的脚本。

        当 CLI 满足不了需求了,就可以使用 Webpack。

        Webpack 算是现代前端开发构建工具中的 中坚力量 (opens new window)。那些众多的 CLI,其实它们的底层封装也都是基于 Webpack。比如我们检索 React CLI 的源码,最终就会发现 使用了 webpack (opens new window)。

        Webpack 非常强大,借助插件系统,能支持各种编译需求。这也导致了它非常复杂,各个插件之间的不兼容情况和 Bug 时有发生。这甚至产生了“高级 Webpack 配置工程师”这样的梗。

        但无论如何,想要成为更资深的工程师或是进行二次开发,了解 Webpack 的基本原理以及使用是必不可少的。

        # Parcel

        • Parcel (opens new window)
        • Parcel 中文网 (opens new window)

        Webpack 过于复杂,CLI 也需要一些配置步骤,
        如果只是做做 Demo,还有一个更方便的选择,那就是 Parcel。

        Parcel 怎么用的?几句话就能讲清楚。

        I have an index.html ~

        <html>
          <head></head>
          <body>
            <div id="app-react"></div>
            <script src="app.tsx"></script>
          </body>
        </html>
        
        1
        2
        3
        4
        5
        6
        7

        I have an app.tsx ~

        import React from 'react';
        import ReactDOM from 'react-dom';
        
        const App: React.FC = () => <div>Hello Parcel!</div>;
        
        ReactDOM.render(
          <App />,
          document.getElementById('app-react'),
        );
        
        1
        2
        3
        4
        5
        6
        7
        8
        9

        Uh!

        parcel index.html
        
        1

        自动预览,自动打包,一个应用就做好了!

        不需要初始化,不需要安装依赖,不需要任何配置。就是这么简单!

        # Rollup、Microbundle

        • rollup.js (opens new window)
        • rollup.js - 中文 (opens new window)
        • Microbundle (opens new window)

        Rollup 和 Microbundle 有点类似 Webpack 和 Parcel,
        差别在于它们更适用于 npm 包的开发而不是 Web 应用。

        比如 React 和 Vue 框架本身,就是用 Rollup 打包的 (opens new window)。

        这里的空白处太小,写不下。 就不多介绍了。

        # 编译器(在线预览)

        这一章节我要介绍的,不是“我如何运行我的代码”,而是“它如何运行我的代码”。

        JS 虽然是解释型语言,直接丢到 Runtime 里就可以运行,使用者不需要懂得编译原理。但对于更资深的工程人员来说,编译原理、以及 JS 的语言设计和运行机制,还是非常有必要了解的。

        # Babel - Try it out

        • Try it out - Babel (opens new window)
        • 试一试 - Babel (opens new window)

        最著名和常用的 Babel 编译器,通常和 Webpack 搭配使用,完成新语法到兼容语法的编译功能。上面有两个在线试用的网址,可以动手玩,看看 Babel 的作用和实现的效果是什么。

        例如:

        箭头函数转成 function 函数

        // * ---------------- 输入
        
        const fn = () => 'Hello';
        
        // * ---------------- 输出
        
        var fn = function fn() {
          return 'Hello';
        };
        
        1
        2
        3
        4
        5
        6
        7
        8
        9

        配合 @babel/preset-react 插件,将 JSX 转义成普通 JS 语法
        (这样就很明显解释了,为什么 React 项目代码中需要 import React)

        // * ---------------- 输入
        
        <div>Hello !</div>;
        
        // * ---------------- 输出
        
        /*#__PURE__*/
        React.createElement('div', null, 'Hello !');
        
        1
        2
        3
        4
        5
        6
        7
        8

        配合 @babel/preset-typescript 插件,将 TS 转义成普通 JS 语法

        // * ---------------- 输入
        
        enum DIR {
          Up = 1,
          Down,
          Left,
          Right,
        }
        
        // * ---------------- 输出
        
        var DIR;
        
        (function (DIR) {
          DIR[(DIR['Up'] = 1)] = 'Up';
          DIR[(DIR['Down'] = 2)] = 'Down';
          DIR[(DIR['Left'] = 3)] = 'Left';
          DIR[(DIR['Right'] = 4)] = 'Right';
        })(DIR || (DIR = {}));
        
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19

        # TypeScript Playground

        TypeScript Playground (opens new window)

        TypeScript 自己的 Playground。除了查看 TS 到 JS 的编译结果,也能直接运行(试试 console 栏)。

        通常在工程实践中使用 TS,只会将 TS 编译到 ESNext(也就是最新的 JS 语法),施加最小的影响。这是因为浏览器可以直接运行 JS 但不能直接运行 TS。

        要是还有兼容性的需求,可以再交给 Babel 进行处理。
        所以我们提到前端编译,通常会一起包括 Webpack + Babel + TypeScript 这三个工具。

        # AST Explorer

        编译的大致原理是:将字符串代码解析成 AST,也就是 Abstract Syntax Tree,抽象语法树;接着进行处理,变换其中的一些数据(例如将 const 关键字改成 var);最后将处理过后的 AST 合并成新的代码。

        事实上不只有 Babel 能做编译。诸如 JS 引擎读取 JS 代码翻译成中间码并执行,TS 对代码语法进行静态检测,JVM 运行 Java 代码,C 语言编译到机器码。这些都需要编译过程。

        AST Explorer (opens new window)

        这个链接可以动手玩,直观地了解编译和抽象语法树的概念。

        比方说,一句简单的 log 代码,

        console.log('Hello');
        
        1

        实际上包含了很多信息,比如:代码长度、调用表达式、成员表达式、标识符、字面量…等等

        Program  {
          type: "Program"
          start: 0
          end: 21
          body:  [
            ExpressionStatement  {
              type: "ExpressionStatement"
              start: 0
              end: 21
              expression: CallExpression  {
                type: "CallExpression"
                start: 0
                end: 20
                callee: MemberExpression {type, start, end, object, property, ... +1}
                arguments: [1 element]
              }
            }
          ]
          sourceType: "module"
        }
        
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20

        # JavaScript Visualizer

        JavaScript Visualizer (opens new window)

        在大致了解了编译原理之后,我们可以继续深入看看 JS 的执行机制。

        众所周知,JS 有词法作用域、函数作用域、函数调用等概念。而这些概念实际上也源自语言设计和实际代码,不是凭空出现的。它们在 JS 引擎中的具体实施是怎样的?我们可以通过上面这个链接,观察代码的逐步运行演示,更深刻地理解这些概念。

        试试 Run 一下我们刚才提到的,简单的 log 方法。

        console.log('Hello');
        
        1

        或者试试函数调用(甚至更复杂的嵌套调用)

        function fn() {
          console.log('Hello');
        }
        
        fn();
        
        1
        2
        3
        4
        5

        通过逐帧观察,就能直观理解 CallExpression、MemberExpression 等那些 AST 中见到的概念。

        需要注意的是,这个项目目前还不支持 ES6+ 的语法(例如 const、=> 等),可以使用 ES5。

        # 在线编辑器

        除了本地开发以外,也会有在线编辑的需求,比方说:向别人展示自己的可运行的代码。

        在线编辑器的好处是,能够直接运行,省去了传统的准备开发编译部署的一系列环节,更新代码也更为方便了。非常适合用作分享。

        甚至也可以作为主力开发环境,VS Code 目前就有开发中的 Web 版。
        这就好比服务器部署现在有 Serverless 等新技术,说不定未来的源码编写工作也可以全部在云端进行。

        这里列举一些我用过站点,其实就相当于本地编辑器的在线简化版,就不多介绍了。

        • StackBlitz (opens new window):演示小型 Demo,可以直接装 npm 包(看看界面是不是跟 VS Code 很像?)
        • CodeSandbox (opens new window):演示小型 Demo,可以直接装 npm 包
        • JS Bin (opens new window):常见于 Stack Overflow 提问时附带演示
        • CodePen (opens new window):高质量的 CSS 作品偏多,可以手动通过 CDN 加载 npm 包

        # 其他

        这一章略有偏题,但也有一定相关性。推荐几个有意思的工具。

        # jsconsole

        jsconsole (opens new window)

        这个网站相当于浏览器的 DevTools。我有时在地铁上只能用手机的时候会用它研究代码片段。

        # Console Importer

        Console Importer (opens new window)

        这是一个 Chrome 的浏览器插件,可以在 console 中直接安装 npm 包并使用。

        比方说:

        $i('lodash');
        
        // 等下载完
        
        _.uniq([2, 1, 2]); // => [2, 1]
        
        1
        2
        3
        4
        5

        分析别人家网页的时候比较方便。

        Console Importer Presentation

        # carbon

        carbon (opens new window)

        一个代码截图的工具(用于分享),样式比较好看。

        carbon screenshot

        # dwitter.net

        dwitter.net (opens new window)

        你能在 140 个字符的极限规模内写出什么代码呢?

        (它实际上利用计时器和 canvas 来运行)

        dwitter show case

        #JavaScript
        上次更新: Nov 18, 2022 10:11 PM
        最近更新
        01
        Linux Shell 快速入门笔记
        11-18
        02
        我的 Web 前端开发知识体系 (2022)
        01-29
        03
        游戏环境研究笔记(2022-01)
        01-16
        更多文章>
        Theme by Vdoing | Copyright © 2019-2022 Seognil LC | MIT License
        • 跟随系统
        • 浅色模式
        • 深色模式
        • 阅读模式