国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

webpack4.x 模塊化淺析-CommonJS

alphahans / 2290人閱讀

摘要:先看下官方文檔中對(duì)模塊的描述在模塊化編程中,開(kāi)發(fā)者將程序分解成離散功能塊,并稱之為模塊。每個(gè)模塊具有比完整程序更小的接觸面,使得校驗(yàn)調(diào)試測(cè)試輕而易舉。

先看下webpack官方文檔中對(duì)模塊的描述:

在模塊化編程中,開(kāi)發(fā)者將程序分解成離散功能塊(discrete chunks of functionality),并稱之為模塊。
每個(gè)模塊具有比完整程序更小的接觸面,使得校驗(yàn)、調(diào)試、測(cè)試輕而易舉。 精心編寫(xiě)的模塊提供了可靠的抽象和封裝界限,使得應(yīng)用程序中每個(gè)模塊都具有條理清楚的設(shè)計(jì)和明確的目的。

webpack 的核心概念之一就是一切皆模塊,webpack 在項(xiàng)目中的作用就是,分析項(xiàng)目的結(jié)構(gòu),找到 JavaScript 模塊以及其他一些瀏覽器不能直接運(yùn)行的拓展語(yǔ)言(less,scss,typescript),并將其打包為合適的格式以供瀏覽器使用,它從一個(gè)項(xiàng)目的主文件開(kāi)始,根據(jù)引用路徑,找到所有其所依賴的文件,同時(shí)將這些文件進(jìn)行處理(各種loader來(lái)解析,編譯處理瀏覽器不能直接使用的文件),然后打包為一個(gè)或者多個(gè)瀏覽器可識(shí)別的JavaScript文件。

本文不會(huì)詳細(xì)描述 webpack 的構(gòu)建流程,畢竟官網(wǎng)已經(jīng)說(shuō)得比較詳細(xì)了,這里主要是分析下 webpack 打包后的文件,將文件打包成什么樣子,又是如何使用模塊的。webpack 最早支持的代碼模塊化方式是 CommonJS,后面慢慢支持了 ES6、AMD 等,不論使用的是哪種方式,webpack 都可以對(duì)其進(jìn)行解析和打包,本文例子中使用的是 CommonJS 規(guī)范,更多規(guī)范介紹可查看官方文檔。

例子

為方便后面的說(shuō)明,首先創(chuàng)建一個(gè)項(xiàng)目,也就是先建立一個(gè)文件夾 webpack-test(名字自擬),在 webpack-test 文件夾中使用命令初始化,會(huì)生成一個(gè) package.json 文件,用來(lái)做 npm 的說(shuō)明:

npm init

執(zhí)行命令后會(huì)詢問(wèn)一些問(wèn)題,一路回車即可。然后安裝下 webpack 的依賴包,如下命令:

npm install --save-dev webpack

再新建幾個(gè)文件:
1、在項(xiàng)目根目錄下新建文件夾 app 用來(lái)存放業(yè)務(wù)代碼、文件夾 public 存放打包后的文件;
2、在app中新建入口文件 main.js;
3、在app中新建功能模塊 hello.js,bye.js,to.js;
4、在項(xiàng)目根目錄下,建立 index.html 文件;

然后依次來(lái)給這幾個(gè)文件分別填寫(xiě)以下內(nèi)容:

// webpack-test/app/hello.js
const to = require("./to.js");
module.exports = function() {
  var hello = document.createElement("div");
  hello.textContent = "Say Hello to " + to.name;
  return hello;
};
// webpack-test/app/bye.js
const to = require("./to.js");
module.exports = function() {
  var bye = document.createElement("div");
  bye.textContent = "Say Bye to " + to.name;
  return bye;
};
// webpack-test/app/to.js
module.exports = {name: "小明"};
// webpack-test/app/main.js
const hello = require("./hello.js");
const bye = require("./bye.js");

document.querySelector("#root").appendChild(hello()).appendChild(bye());;
// webpack-test/index.html


  
    
    Webpack Test Project
  
  
    
// bundle.js 文件就是一會(huì)兒我們要打包app中的文件后生成的結(jié)果文件

業(yè)務(wù)模塊 hello.js 和 bye.js 做了各自的操作,同時(shí)引用了共同的文件 to.js;主文件 main.js 中引用并執(zhí)行了模塊 hello.js 和 bye.js;index.html 文件引入了 main.js 打包后的最終文件 bundle.js。

打包

接下來(lái)進(jìn)行打包操作,先確保 webpack 是全局安裝的,否則執(zhí)行時(shí)需要指定 webpack 的路徑,比如在 4.0 以下版本中使用 node_modules/.bin/webpack ./app/main.js ./public/bundle.js;
如果你使用的是 webpack4.0+ 的話,使用 webpack ./app/main.js ./public/bundle.js命令,也許會(huì)報(bào)以下的錯(cuò)誤:

WARNING in configuration
The "mode" option has not been set, webpack will fallback to "production" for this value. Set "mode" option to "development" or "production" to enable defaults for each environment.
You can also set it to "none" to disable any default behavior. Learn more: https://webpack.js.org/concepts/mode/

ERROR in multi ./app/main.js ./public/bundle.js
Module not found: Error: Can"t resolve "./public/bundle.js" in "/Users/zhaohaipeng/soyoung-project/webpack-test"
 @ multi ./app/main.js ./public/bundle.js main[1]

webpack4.0+之后,針對(duì)第一個(gè)報(bào)錯(cuò),需要指定環(huán)境 --mode development;第二個(gè)報(bào)錯(cuò),是因?yàn)槲覀儧](méi)有使用配置文件的方式打包,而是直接使用的命令指定的打包輸出位置,所以需要聲明輸出文件,綜上,正確的命令如下:

webpack app/main.js --output public/bundle.js --mode development

執(zhí)行結(jié)果:

?  webpack-test webpack app/main.js --output public/bundle.js --mode development
Hash: a4e2f9ecc51b64891624
Version: webpack 4.25.1
Time: 90ms
Built at: 2018-11-08 17:11:01
    Asset      Size  Chunks             Chunk Names
bundle.js  5.16 KiB    main  [emitted]  main
Entrypoint main = bundle.js
[./app/bye.js] 165 bytes {main} [built]
[./app/hello.js] 173 bytes {main} [built]
[./app/main.js] 144 bytes {main} [built]
[./app/to.js] 30 bytes {main} [built]
?  webpack-test

瀏覽器打開(kāi) index.html 文件,即可看到結(jié)果

Say Hello to 小明
Say Bye to 小明

但是 webpack 作為一個(gè)能簡(jiǎn)化我們開(kāi)發(fā)難度和使用便捷的工具,顯然像上面那樣通過(guò)敲很多命令來(lái)打包,并不方便,所以下面采用配置文件的方式再來(lái)一次:

根目錄創(chuàng)建 webpack.config.js 文件,并配置下打包入口和出口:

// webpack-test/webpack.config.js
module.exports = {
    mode: "development",//webpack.0之后需要聲明環(huán)境
    entry:  __dirname + "/app/main.js",//唯一入口文件
    output: {
        path: __dirname + "/public",//打包后的文件存放目錄
        filename: "bundle.js"http://打包后輸出文件名
    }
}

再次打包的時(shí)候,只需要使用命令 webpack 就可以了,webpack 默認(rèn)讀取當(dāng)前路徑下的 webpack.config.js 文件。

最終打包好的 bundle.js 文件,去除了多余注釋,調(diào)整了代碼格式,內(nèi)容如下:

// 自執(zhí)行函數(shù),參數(shù)為所有模塊組成的,形勢(shì)為key:value,key是模塊名
(function(modules) { // webpackBootstrap
    // 已加載模塊的緩存,記錄模塊的加載情況,也是為了避免重復(fù)打包,節(jié)省資源
    var installedModules = {};

    // webpack 使用 require 方式加載模塊的方法(模擬ConmmonJS reqiure()),作用為根據(jù)傳進(jìn)來(lái)的模塊id來(lái)處理對(duì)應(yīng)的模塊,加入已加載緩存,執(zhí)行,標(biāo)記,返回exports
    function __webpack_require__(moduleId) {
       // moduleId 為模塊路徑
        // 檢測(cè)模塊是否已加載,已加載的話直接返回該模塊
        if(installedModules[moduleId]) {
            return installedModules[moduleId].exports;
        }
        // 當(dāng)前模塊未加載的話,新建,并存于緩存
        var module = installedModules[moduleId] = {
            i: moduleId,
            l: false,
            exports: {}
        };

        // 在當(dāng)前模塊的 exports 下,也就是模塊的內(nèi)部執(zhí)行模塊代碼,突出作用域
        modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);

        // 標(biāo)記模塊已經(jīng)加載
        module.l = true;

        // 返回模塊的導(dǎo)出內(nèi)容
        return module.exports;
    }


    // 掛載屬性,該模塊 (__webpack_modules__)
    __webpack_require__.m = modules;

    // 掛載屬性,模塊加載緩存
    __webpack_require__.c = installedModules;

    // 本代碼中未執(zhí)行,暫時(shí)不分析
    // 在 exports 中定義 getter 方法
    __webpack_require__.d = function(exports, name, getter) {
        // 當(dāng) name 屬性不是定義在對(duì)象本身,而是繼承自原型鏈,則在在 exports 中定義 傳進(jìn)來(lái)的 name 屬性,和這個(gè)屬性的 getter 方法
        if(!__webpack_require__.o(exports, name)) {
            Object.defineProperty(exports, name, { enumerable: true, get: getter });
        }
    };

    // 給exports定義類型
    // 在 exports 中定義 __esModule,定義key為Symbol的屬性(在__webpack_require__.t中被調(diào)用)
    // define __esModule on exports
    __webpack_require__.r = function(exports) {
        if(typeof Symbol !== "undefined" && Symbol.toStringTag) {
            // 對(duì)象定義為 Module 類型
            Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
        }
        // 給對(duì)象exports添加屬性 __esModule
        Object.defineProperty(exports, "__esModule", { value: true });
    };

    // 本代碼中未執(zhí)行,暫時(shí)不分析
    // 創(chuàng)建一個(gè)偽命名空間的對(duì)象
    // create a fake namespace object
    // mode & 1: value is a module id, require it
    // mode & 2: merge all properties of value into the ns
    // mode & 4: return value when already ns object
    // mode & 8|1: behave like require
    __webpack_require__.t = function(value, mode) {
        if(mode & 1) value = __webpack_require__(value);
        if(mode & 8) return value;
        if((mode & 4) && typeof value === "object" && value && value.__esModule) return value;
        var ns = Object.create(null);
        __webpack_require__.r(ns);
        Object.defineProperty(ns, "default", { enumerable: true, value: value });
        if(mode & 2 && typeof value != "string") for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
        return ns;
    };

    // 本代碼中未執(zhí)行,暫時(shí)不分析
    // getDefaultExport function for compatibility with non-harmony modules
    __webpack_require__.n = function(module) {
        var getter = module && module.__esModule ?
            function getDefault() { return module["default"]; } :
            function getModuleExports() { return module; };
        __webpack_require__.d(getter, "a", getter);
        return getter;
    };

    // Object.prototype.hasOwnProperty.call
    // 判斷一個(gè)屬性是定義在對(duì)象本身而不是繼承自原型鏈
    __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };

    // __webpack_public_path__
    __webpack_require__.p = "";


    // 加載入口模塊 main.js ,返回 exports,從而從入口文件開(kāi)始執(zhí)行,以遞歸的方式,將所有依賴執(zhí)行并返回
    return __webpack_require__(__webpack_require__.s = "./app/main.js");
})({

    "./app/bye.js": (function(module, exports, __webpack_require__) {

        eval("const to = __webpack_require__(/*! ./to.js */ "./app/to.js");
module.exports = function() {
  var bye = document.createElement("div");
  bye.textContent = "Say Bye to " + to.name;
  return bye;
};

//# sourceURL=webpack:///./app/bye.js?");

    }),

    "./app/hello.js": (function(module, exports) {

        eval("module.exports = function() {
  var hello = document.createElement("div");
  hello.textContent = "Say Hello!";
  return hello;
};

//# sourceURL=webpack:///./app/hello.js?");

    }),

    "./app/main.js": (function(module, exports, __webpack_require__) {

        eval("const hello = __webpack_require__(/*! ./hello.js */ "./app/hello.js");
const bye = __webpack_require__(/*! ./bye.js */ "./app/bye.js");

document.querySelector("#root").appendChild(hello()).appendChild(bye());;

//# sourceURL=webpack:///./app/main.js?");

    }),

    "./app/to.js": (function(module, exports) {

        eval("module.exports = {name: "小明"};

//# sourceURL=webpack:///./app/to.js?");

    })

});
分析

webpack 的運(yùn)行過(guò)程可分為:讀取配置參數(shù),實(shí)例化插件,模塊解析處理(loader),輸出打包文件;在上面例子中,僅為 JavaScript 的引用,沒(méi)有使用插件和像CSS、less、圖片之類需要loader處理的模塊,所以上面的例子,過(guò)程只有讀取配置,識(shí)別入口及其引用模塊,打包幾步,生成最終的 bundle.js 文件。

簡(jiǎn)單描述下 webpack 在這個(gè)過(guò)程中的執(zhí)行流程:在配置文件中讀取入口,如果有配置 plugins 參數(shù),那么也是在此時(shí)進(jìn)行插件的實(shí)例化和鉤子函數(shù)的綁定;模塊解析,也就是loader加入的時(shí)刻,從入口文件開(kāi)始,根據(jù)入口文件對(duì)其他模塊的依賴,結(jié)合配置文件中對(duì)不同種類型文件所使用的 loader(加載器) 說(shuō)明,一個(gè)一個(gè)逐級(jí)對(duì)這些模塊進(jìn)行解析處理,或壓縮,或轉(zhuǎn)義,生成瀏覽器可以直接識(shí)別的內(nèi)容;最后將所有模塊進(jìn)行打包,輸出打包后的文件。在上面的代碼中,已經(jīng)對(duì) bundle.js 內(nèi)容進(jìn)行了內(nèi)容注釋,下面我們來(lái)分析下 bundle.js 的執(zhí)行過(guò)程:

1、自執(zhí)行函數(shù)

最后的輸出的文件 bundle.js 是一個(gè) JavaScript 文件,其本身其實(shí)是一個(gè)自執(zhí)行函數(shù)

(function(參數(shù)){})(參數(shù))。

2、參數(shù)

自執(zhí)行方法的參數(shù)為所有模塊組成的對(duì)象,key 為各個(gè)模塊的路徑,值為各模塊內(nèi)部的執(zhí)行代碼,觀察參數(shù)內(nèi)部的代碼,對(duì)比打包前的源碼,可以發(fā)現(xiàn)凡是 require 都變成了__webpack_require__這個(gè)webpack自定義的模塊調(diào)用方法,而且源碼中的相對(duì)路徑也變成了最終執(zhí)行位置的文件的相對(duì)路徑。

{

    "./app/bye.js": (function(module, exports, __webpack_require__) {

        eval("const to = __webpack_require__(/*! ./to.js */ "./app/to.js");
module.exports = function() {
  var bye = document.createElement("div");
  bye.textContent = "Say Bye to " + to.name;
  return bye;
};

//# sourceURL=webpack:///./app/bye.js?");

    }),

    "./app/hello.js": (function(module, exports) {

        eval("module.exports = function() {
  var hello = document.createElement("div");
  hello.textContent = "Say Hello!";
  return hello;
};

//# sourceURL=webpack:///./app/hello.js?");

    }),

    "./app/main.js": (function(module, exports, __webpack_require__) {

        eval("const hello = __webpack_require__(/*! ./hello.js */ "./app/hello.js");
const bye = __webpack_require__(/*! ./bye.js */ "./app/bye.js");

document.querySelector("#root").appendChild(hello()).appendChild(bye());;

//# sourceURL=webpack:///./app/main.js?");

    }),

    "./app/to.js": (function(module, exports) {

        eval("module.exports = {name: "小明"};

//# sourceURL=webpack:///./app/to.js?");

    })

}

3、執(zhí)行

(1)自執(zhí)行文件開(kāi)始執(zhí)行后,到自執(zhí)行函數(shù)最底部,首先從入口文件開(kāi)始加載

return __webpack_require__(__webpack_require__.s = "./app/main.js");

(2)__webpack_require__函數(shù)被調(diào)用,傳入?yún)?shù) ./app/main.js,

function __webpack_require__(moduleId) {
        // moduleId 為 ./app/main.js
        // 首次進(jìn)來(lái),未加載,模塊還沒(méi)有緩存
        if(installedModules[moduleId]) {
            return installedModules[moduleId].exports;
        }
        // 新建 ./app/main.js 模塊,并存于緩存
        var module = installedModules[moduleId] = {
            i: moduleId,
            l: false,
            exports: {}
        };

        modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);

        // 標(biāo)記模塊已經(jīng)加載
        module.l = true;

        // 輸出模塊的內(nèi)容
        return module.exports;
    }

此時(shí)方法中執(zhí)行 modules[moduleId].call(module.exports, module, module.exports,__webpack_require__); 相當(dāng)于在名為 ./app/main.js 的模塊中執(zhí)行如下代碼:

(function(module, exports, __webpack_require__) {

        eval("const hello = __webpack_require__(/*! ./hello.js */ "./app/hello.js");
const bye = __webpack_require__(/*! ./bye.js */ "./app/bye.js");

document.querySelector("#root").appendChild(hello()).appendChild(bye());;

//# sourceURL=webpack:///./app/main.js?");

})()

由于引用關(guān)系,接下來(lái)會(huì)再次執(zhí)行兩次__webpack_require__方法,分別傳參模塊路徑 ./app/hello.js 和 ./app/bye.js;

(3)執(zhí)行第一個(gè)__webpack_require__過(guò)程,除了傳參不同、執(zhí)行的模塊不同,與第二步基本一致,再次找到了依賴模塊 to.js,再次調(diào)用__webpack_require__。

"./app/hello.js": (function(module, exports, __webpack_require__) {

    eval("const to = __webpack_require__(/*! ./to.js */ "./app/to.js");
module.exports = function() {
  var hello = document.createElement("div");
  hello.textContent = "Say Hello to " + to.name;
  return hello;
};

//# sourceURL=webpack:///./app/hello.js?");

}),

(4)執(zhí)行第二個(gè)__webpack_require__時(shí),在 bye.js 中找到了對(duì)于 to.js 的依賴,所以將繼續(xù)調(diào)用__webpack_require__方法,只是傳參變成了./app/to.js,達(dá)到終點(diǎn)。

"./app/bye.js": (function(module, exports, __webpack_require__) {

        eval("const to = __webpack_require__(/*! ./to.js */ "./app/to.js");
module.exports = function() {
  var bye = document.createElement("div");
  bye.textContent = "Say Bye to " + to.name;
  return bye;
};

//# sourceURL=webpack:///./app/bye.js?");

})

(5)到此時(shí),整個(gè)從入口文件的開(kāi)始的針對(duì)所依賴模塊的解析已經(jīng)完成,所有的 js 代碼也已經(jīng)引用完畢且放到了 bundle.js 中。

總結(jié)

到這里可以看到,webpack對(duì)js的打包,就是封裝為一個(gè)個(gè)多帶帶的方法,通過(guò)對(duì)這些方法的引用,達(dá)到模塊化的效果;而打包的過(guò)程,就是查找、解析、封裝這些方法的過(guò)程,整個(gè)執(zhí)行路徑類似于一棵樹(shù),從主干出發(fā),沿著樹(shù)枝遞歸式的執(zhí)行“require”方法,而且是直到這一根樹(shù)枝走到盡頭的時(shí)候才回頭尋找其他的方法,由于node的單線程,當(dāng)項(xiàng)目龐大或者模塊間依賴錯(cuò)綜復(fù)雜時(shí),webpack打包會(huì)更加的耗費(fèi)時(shí)間。

以上為對(duì)webpack4.x中針對(duì)js模塊處理的簡(jiǎn)單理解,主要基于官方文檔的介紹和打包后文件的分析,源碼讀起來(lái)還是比較難懂,暫時(shí)不敢照量。對(duì)于 ES6、AMD 的模塊化方式,代碼分割的等,后續(xù)再進(jìn)行補(bǔ)充。

以上如有問(wèn)題,歡迎指正!

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/99118.html

相關(guān)文章

  • webpack4.x升級(jí)摘要

    摘要:以為例,編寫(xiě)來(lái)幫助我們完成重復(fù)的工作編譯壓縮我只要執(zhí)行一下就可以檢測(cè)到文件的變化,然后為你執(zhí)行一系列的自動(dòng)化操作,同樣的操作也發(fā)生在這些的預(yù)處理器上。的使用是針對(duì)第三方類庫(kù)使用各種模塊化寫(xiě)法以及語(yǔ)法。 showImg(https://segmentfault.com/img/bVbtZYK); 一:前端工程化的發(fā)展 很久以前,互聯(lián)網(wǎng)行業(yè)有個(gè)職位叫做 軟件開(kāi)發(fā)工程師 在那個(gè)時(shí)代,大家可能...

    levinit 評(píng)論0 收藏0
  • 使用塊化工具打包自己開(kāi)發(fā)的JS庫(kù)

    摘要:平時(shí)有使用過(guò)和開(kāi)發(fā)的同學(xué),應(yīng)該能體會(huì)到模塊化開(kāi)發(fā)的好處。原因很簡(jiǎn)單打包出來(lái)的使用了關(guān)鍵字,而小程序內(nèi)部并支持。是一個(gè)模塊打包器,可以將小塊代碼編譯成大塊復(fù)雜的代碼,例如或應(yīng)用程序。官網(wǎng)的這段介紹,正說(shuō)明了就是用來(lái)打包的。 博客地址 最近有個(gè)需求,需要為小程序?qū)懸粋€(gè)SDK,監(jiān)控小程序的后臺(tái)接口調(diào)用和頁(yè)面報(bào)錯(cuò)(類似fundebug) 聽(tīng)起來(lái)高大上的SDK,其實(shí)就是一個(gè)JS文件,類似平時(shí)開(kāi)發(fā)...

    AprilJ 評(píng)論0 收藏0
  • webpack4.x深入與實(shí)踐

    摘要:它將根據(jù)模塊的依賴關(guān)系進(jìn)行靜態(tài)分析,然后將這些模塊按照指定的規(guī)則生成對(duì)應(yīng)的靜態(tài)資源。可以將多種靜態(tài)資源轉(zhuǎn)換成一個(gè)靜態(tài)文件,減少了頁(yè)面的請(qǐng)求。因此我們不再按文件文件的方式運(yùn)行指令,而是直接運(yùn)行這樣便能實(shí)現(xiàn)打包。 一、什么是webpack 是一個(gè)前端資源加載/打包工具。它將根據(jù)模塊的依賴關(guān)系進(jìn)行靜態(tài)分析,然后將這些模塊按照指定的規(guī)則生成對(duì)應(yīng)的靜態(tài)資源。它做的事情是,分析你的項(xiàng)目結(jié)構(gòu),找到J...

    Lsnsh 評(píng)論0 收藏0
  • 基于webpack4.x, babel7.x 搭建的多頁(yè)面腳手架, 簡(jiǎn)化前端開(kāi)發(fā)環(huán)境配置,開(kāi)箱即用,

    摘要:開(kāi)箱即用的多頁(yè)面腳手架基于模塊化開(kāi)發(fā)可復(fù)用的現(xiàn)代化網(wǎng)站感興趣的朋友,請(qǐng)點(diǎn)個(gè)及時(shí)關(guān)注項(xiàng)目更新請(qǐng)點(diǎn)個(gè)項(xiàng)目請(qǐng)?zhí)崽匦灾С智昂蠖朔蛛x開(kāi)發(fā)配置完整的打包方案支持本地開(kāi)發(fā)熱更新集成代碼風(fēng)格校驗(yàn)支持編寫(xiě)源碼,編譯生成生產(chǎn)代碼內(nèi)置開(kāi)發(fā)環(huán)境,自動(dòng)加樣式前綴自 Webpack-seed 開(kāi)箱即用的多頁(yè)面腳手架, 基于webpack4.2x babel7.1x模塊化開(kāi)發(fā)可復(fù)用的現(xiàn)代化網(wǎng)站(Without Vu...

    junfeng777 評(píng)論0 收藏0
  • JS或Jquery

    摘要:大潮來(lái)襲前端開(kāi)發(fā)能做些什么去年谷歌和火狐針對(duì)提出了的標(biāo)準(zhǔn),顧名思義,即的體驗(yàn)方式,我們可以戴著頭顯享受沉浸式的網(wǎng)頁(yè),新的標(biāo)準(zhǔn)讓我們可以使用語(yǔ)言來(lái)開(kāi)發(fā)。 VR 大潮來(lái)襲 --- 前端開(kāi)發(fā)能做些什么 去年谷歌和火狐針對(duì) WebVR 提出了 WebVR API 的標(biāo)準(zhǔn),顧名思義,WebVR 即 web + VR 的體驗(yàn)方式,我們可以戴著頭顯享受沉浸式的網(wǎng)頁(yè),新的 API 標(biāo)準(zhǔn)讓我們可以使用 ...

    CatalpaFlat 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<