Giter VIP home page Giter VIP logo

blog's People

Contributors

bigbossx avatar

Watchers

 avatar

blog's Issues

关于 webpack

哎~朋友们好啊,我是练习时长三年半的前端小老板,昨天有个朋友问我,b导师,发生甚么事了,我说怎么回事,给我发了几张截图,我一看,哦,原来是佐天,有两个年轻人,20多岁,一个刚毕业,一个工作一年多了,塔门说,哎~有一个说是,我在天天在src目录下写代码,开发,一点进步都没有,b导师,你能不能教教我webpack相关的知识,哎~帮助学习一下。我说可以,我说你在src目录下练死劲不管用,他不服气。哎~我说小朋友,看我教你怎么跑项目,他说你这也没用。我说我这个有用,这是项目配置,传统前端是讲工程化的,四两拨千金, ​国内国外很多大公司前端项目走的都是这样的流程,他说要我试试,我说可以,哎~我说一完他啪的一下就坐过来了,很快啊!然后我上来就是一个npm install 咳!一个npm start 全部成功了,成功了啊,成功了以后自然是传统前端,8080端口,输在浏览器上没打开,我笑一下准备 ctrol c,因为这时间,按照传统前端的流程,已经打包完了,他也承认,都没报错,他承认是我跑成功了啊,我ctrol c的时间,不跑了,他突然说一句,配置了构建完之后自动打开p站,我大意了啊,没有删,哎~很快就自动打开浏览器,当时很多同事看到了,我说婷婷,但没关系啊,两分多钟之后我关闭了,我说小伙子你不讲伍德,他说b导师对不起对不起,我不懂配置,我是乱加的,他说他是乱加的他可不是乱加的啊,webpack函数 一个配置对象,一个成功回调,训练有素,后来他说他看过几章webpack文档,看来是有备而来,我劝!这位年轻人耗子尾汁,构建,要讲环境,以安全可靠为贵,不要再犯这样的聪明,小聪明啊,谢谢朋友们。

开篇

我们通常将源码 -> 产物的过程称之为打包或者叫构建,在此过程中,我们将获取到源代码内容,重新组装,转换,压缩,混淆,修改...等等一系列的操作,以达到一些非常简单原始的目的:

  • 舒适的开发体验
  • 安全可靠的运行逻辑
  • 良好的用户体验
  • ...

通常来说越复杂的东西,越应该精细化和自动化,工具化等,webpack也是在web应用逐渐复杂的背景下诞生的。

我习惯了解一个东西先去了解时代背景,作者一开始的**,这样我能更快的知道他为什么做,当时能怎么做,后来怎么做了更多。思路 > 代码实现,当然代码实现仍然是我们非常应该学习然后积累的点。

正文

webpack 开始于2012年 sokra 的一个被拒绝的功能请求 medikoo/modules-webmake#7 基于modules-webmake sokra提出,增加类似Code Splitting的功能。即我们的构建可以有如下的功能:

  • 1、allows you to organize JavaScript code for the browser the same way as you do for Node.js.
  • 2、Code Splitting
  • 3、支持加载 image 和 css

让我们回头来看看,这些是什么,然后在解决什么问题,首先是

Allows you to organize JavaScript code for the browser the same way as you do for Node.js.

我们知道js在esm之前并没有模块规范标准,但是随着web应用的不断复杂化,代码的模块化成为不可或缺的一点,你可以在这些文章详细了解

不再赘述,但我们总结出几个关键点:(在js esm规范之前)
1、AMD CMD 等实现,都有一个函数包裹,即回调函数内,才是模块代码,再详细一点呢?

  • 由于在浏览器环境,网络传输层面的未知延时。我们不能等到const xxx=require("xxx")执行的那一刻才去用script加载xxx.js ,无法同步获取模块的导出
  • 浏览器没有文件内作用域的概念,即在浏览器中a.js b.js 是共享全局变量的,所以仍然是有变量冲突的问题,更没有module这个对象让我们可以在不同js文件中互操作
  • 我们可以将不同的文件内容,通过函数包裹,使用函数作用域解决变量冲突和实现模块之间的导出导入(模块化)

相反nodejs则没有那层函数包裹,module exports require __dirname __filename 都是当前文件的,文件之间变量是隔离的,node是怎么做到的?答案是

  • nodejs 是本地文件的io操作,速度非常快,所以可以等到const xxx=require("xxx")执行那一刻再去初始化xxx模块并获得导出
  • nodejs帮我们隐藏了那层函数包裹。

image

我们从上面的知识已经知道了,不管是AMD CMD还是commonjs,他都是函数包裹的函数作用域
那我们通过构建这一层,使得在开发时去掉这层包裹,由构建工具自动补上,不就跟nodejs一模一样了吗!
所以最终,我们知道了如果我们产物长这个样子,那我们的commonjs风的代码,是可以在浏览器完完整整的运行起来的。即实现了allows you to organize JavaScript code for the browser the same way as you do for Node.js

(function(modules /* 所有可用的模块 */) {
        var installModules = {};
        function magicRequire(id) {
          if (installModules[id]) {
            return installModules[id].exports;
          }
          var module = (installModules[id] = {
            exports: {},
            id: id,
          });
          modules[id](module, module.exports, magicRequire); 
          // modules[id].call(module,module, module.exports, magicRequire); // commonjs 规范,this指向当前模块
          return module.exports;
        }
        magicRequire("entry");
})({
    "entry": function(module, exports, require) {
        var addModule = require("./add");
        const temp = addModule.add(1, 1);
        var { square } = require("./square");
        console.log(square(temp,temp))
    },
    "./add": function(module, exports, require) {
        module.exports = {
            add: function(x, y) {
                return x + y;
            }
        };
    },
    "./square": function(module, exports, require) {
        var { multiply } = require("./multiply");
        module.exports = {
            square: function(num) {
                return multiply(num, num);
            }
        };
    },
    "./multiply": function(module, exports, require) {
        module.exports = {
            multiply: function(x, y) {
                return x * y;
            }
        };
    }
})

这也即是webpack所说的runtime 运行时 + modules 模块,由runtime组织起来module之间的逻辑运行

那Code Splitting是啥

从上面的产物可以知道,这个产物是一个js文件,它不止一个module,所以我们不能再叫module了,给它取了个时兴的名字:chunk 上面这个chunk = runtime + module 。我们可以再进一步把它拆分, runtime 独立出来,叫runtime chunk,modules 部分就叫module chunk吧。

modules就是当前我们所有可用的模块集合,但是,我们的项目可能非常庞大,所以如果将所有的模块组合在同一个js 里面,将会非常大,所以我们需要有组织的将modules 的部分拆分出去。拆分出去的这一部分多个模块组成的js产物文件,我们称为异步chunk

然后我们提供一个类似jsonp的方案,sciprt标签加载异步chunk,通过jsonp回调将额外的module merge 到modules 中,即

(function(modules /* 所有可用的模块 */) {
  // ...
  window.webpackJsonp=function(chunkid,moreModules){
    for(const key of moreModules){
      modules[key]=moreModules[key]
    }
  }
})({
// ...
})

// a.chunk.sd2321sd.js
webpackJsonp("sd2321sd",{
  'more1':function(){...},
  'more2':function(){...},
  'more3':function(){...},
})

好了1、2点已经实现了,让我们再加上image和css的加载,其实也非常简单。

对于图片,我们require它的时候,我们希望返回的是一个合法的src 源就可以,例如base64,或者是一个url路径
对于css ,我们require它的时候,我们需要做的就是创建一个style,并且append 到 document head 就可以。

{
    image: function (module, exports, require) {
      module.exports = "/images/header.ada3q43.jpg";
    },
    css: function (module, exports, require) {
      var style = "h1[data-v-1111]{color:yellow;}"; // scoped
      const styleElem = document.createElement("style");
      styleElem.innerHTML = style;
      document.head.appendChild(styleElem);
    },
}

所以,我们现在可以知道了,webpack 的构建核心,是生成组织者:runtime 和各个module的组合:modules
我们来试试,手把手的构建一次,一个mini react hello world

const react = require("react");
const reactDom = require("react-dom");
const reactIcon= require("react-icon")
var image= react.createElement("img", { src: reactIcon }, null)
var component = react.createElement("h1",{},"Hello ", image ,". Welcome!");
reactDom.render(component, document.getElementById("app"));

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.