详解webpack 入门与解析


Posted in Javascript onApril 09, 2018

每次学新东西总感觉自己是不是变笨了,看了几个博客,试着试着就跑不下去,无奈只有去看官方文档。 webpack是基于node的。先安装最新的node。

1.初始化

安装node后,新建一个目录,比如html5。cmd中切到当前文件夹。

npm init -y

这个命令会创建一个默认的package.json。它包含了项目的一些配置参数,通过它可以进行初始安装。详细参数:https://docs.npmjs.com/files/package.json。

不要y参数的话,会在命令框中设置各项参数,但觉得没啥必要。

2.安装webpack

npm install webpack --save-dev

将webpack安装到当前目录。虽然npm install webpack -g 可以讲webpack安装到全局,但是容易出现一些模块找不到的错误,所以最好还是安装到当前目录下。

3.目录结构

webpack是一款模块加载各种资源并打包的工具。所以先建一个如下的目录结构:

详解webpack 入门与解析

app包含的开发中的js文件,一个组件,一个入口。build中就是用来存放打包之后的文件的。webpack.config.js 顾名思义用来配置webpack的。package.json就不用说了。

component.js

export default function () {
 var element = document.createElement('h1');
 element.innerHTML = 'Hello world';
 return element;
}

component.js 是输出一个内容为h1元素。export default 是ES6语法,表示指定默认输出。import的时候不用带大括号。

index.js

import component from './component';
document.body.appendChild(component());

index.js 的作用就是引用Component模块,并在页面上输出一个h1元素。但完成这个还需要一个插件,因为目前我们还没有index.html文件。

npm install html-webpack-plugin --save-dev

html-webpack-plugin的用来生成html,将其也安装到开发目录下面。

4.设置 webpack 配置文件

我们需要通过webpack.config.js文件告诉webpack如何开始。配置文件至少需要一个入口和一个输出。多个页面就需要多个入口。node的path模块

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

const PATHS = {
 app: path.join(__dirname, 'app'),
 build: path.join(__dirname, 'build'),
};

module.exports = {
 entry: {
 app: PATHS.app,
 },
 output: {
 path: PATHS.build,
 filename: '[name].js',
 },
 plugins: [
 new HtmlWebpackPlugin({
  title: 'Webpack demo',
 }),
 ],
};

第一次看到这个配置文件是有点懵,主要是exports,分三个部分,一个入口,一个输出,一个插件。入口指向了app文件夹。默认会把包含"index.js"的文件作为入口。输出指定了build地址和一个文件名;[name]这儿表示占位符,可以看成webpack提供的一个变量。这个具体后面再看。而HtmlWebpackPlugin会生成一个默认的html文件。

5.打包

有了以上准备,直接输入 webpack 就能运行了。

详解webpack 入门与解析

这个输出包含了Hash(每次打包值都不同),Version,Time(耗时)。以及输出的文件信息。这时打开build文件夹,发现多了一个app.js和index.html文件,双击index.html:

详解webpack 入门与解析

也可以修改下package.json

{
 "name": "Html5",
 "version": "1.0.0",
 "description": "",
 "main": "index.js",
 "scripts": {
 "build": "webpack"
 },
 "keywords": [],
 "author": "",
 
 "license": "ISC",
 "devDependencies": {
 "html-webpack-plugin": "^2.28.0",
 "webpack": "^2.2.1"
 }
}

指定build。在cmd中执行npm run build 得到同样的结果

详解webpack 入门与解析

出现helloword。再看下文件内容

index.html:

<!DOCTYPE html>
<html>
 <head>
 <meta charset="UTF-8">
 <title>Webpack demo</title>
 </head>
 <body>
 <script type="text/javascript" src="app.js"></script></body>
</html>

默认引用了app.js。

6、解析

app.js

/******/ (function(modules) { // webpackBootstrap
/******/  // The module cache
/******/  var installedModules = {};

/******/  // The require function
/******/  function __webpack_require__(moduleId) {

/******/   // Check if module is in cache
/******/   if(installedModules[moduleId])
/******/    return installedModules[moduleId].exports;

/******/   // Create a new module (and put it into the cache)
/******/   var module = installedModules[moduleId] = {
/******/    i: moduleId,
/******/    l: false,
/******/    exports: {}
/******/   };

/******/   // Execute the module function
/******/   modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);

/******/   // Flag the module as loaded
/******/   module.l = true;

/******/   // Return the exports of the module
/******/   return module.exports;
/******/  }


/******/  // expose the modules object (__webpack_modules__)
/******/  __webpack_require__.m = modules;

/******/  // expose the module cache
/******/  __webpack_require__.c = installedModules;

/******/  // identity function for calling harmony imports with the correct context
/******/  __webpack_require__.i = function(value) { return value; };

/******/  // define getter function for harmony exports
/******/  __webpack_require__.d = function(exports, name, getter) {
/******/   if(!__webpack_require__.o(exports, name)) {
/******/    Object.defineProperty(exports, name, {
/******/     configurable: false,
/******/     enumerable: true,
/******/     get: getter
/******/    });
/******/   }
/******/  };

/******/  // 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
/******/  __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };

/******/  // __webpack_public_path__
/******/  __webpack_require__.p = "";

/******/  // Load entry module and return exports
/******/  return __webpack_require__(__webpack_require__.s = 1);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
/* harmony default export */ __webpack_exports__["a"] = function () {
 var element = document.createElement('h1');
 element.innerHTML = 'Hello world';
 return element;
};

/***/ }),
/* 1 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__component__ = __webpack_require__(0);

document.body.appendChild(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__component__["a" /* default */])());

/***/ })
/******/ ]);

而app.js内容比较多了。整体是一个匿名函数。

(function(module) {
})([(function (){}), function() {}])

app文件夹中的两个js文件成了这儿的两个模块。函数最开始是从__webpack_require__开始

return __webpack_require__(__webpack_require__.s = 1);

这里指定从模块1执行(赋值语句的返回值为其值)。而模块1的调用是通过__webpack_require__的这句执行的。

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

通过call调用模块的主要作用是为了把参数传过去。

(function(module, __webpack_exports__, __webpack_require__) {

"use strict";
Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__component__ = __webpack_require__(0);

document.body.appendChild(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__component__["a" /* default */])());

/***/ })

__webpack_require__ 每加载一个模块都会先去模块缓存中找,没有就新建一个module对象:

var module = installedModules[moduleId] = {
   i: moduleId,
   l: false,
   exports: {}
  };

模块1中加载了模块0,

var __WEBPACK_IMPORTED_MODULE_0__component__ = __webpack_require__(0);

__WEBPACK_IMPORTED_MODULE_0__component__ 返回的是这个模块0的exports部分。而之前Component.js的默认方法定义成了

__webpack_exports__["a"] = function () {
var element = document.createElement('h1');
element.innerHTML = 'Hello world';
return element;
}

所以再模块1的定义通过"a“来获取这个方法:

document.body.appendChild(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__component__["a" /* default */])());

这样就完整了,但这里使用了__webpack_require__.i 将原值返回。

/******/  // identity function for calling harmony imports with the correct context
/******/  __webpack_require__.i = function(value) { return value; };

不太明白这个i函数有什么作用。这个注释也不太明白,路过的大神希望可以指点下。

小结:

webpack通过一个立即执行的匿名函数将各个开发模块作为参数初始化,每个js文件(module)对应一个编号,每个js中export的方法或者对象有各自指定的关键字。通过这种方式将所有的模块和接口方法管理起来。然后先加载最后的一个模块(应该是引用别的模块的模块),这样进而去触发别的模块的加载,使整个js运行起来。到这基本了解了webpack的功能和部分原理,但略显复杂,且没有感受到有多大的好处。继续探索。

demo:webpack_3water.rar建议用最新的node安装,不然build后的结果可能出错。

参考:

https://survivejs.com/webpack/developing/getting-started/

https://webpack.js.org/

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
一句话JavaScript表单验证代码
Aug 02 Javascript
JQuery动态创建DOM、表单元素的实现代码
Aug 09 Javascript
基于JQuery的模拟苹果桌面Dock效果(稳定版)
Oct 15 Javascript
fckeditor粘贴Word时弹出窗口取消的方法
Oct 30 Javascript
JS代码防止SQL注入的方法(超简单)
Apr 12 Javascript
js实现移动端编辑添加地址【模仿京东】
Apr 28 Javascript
AngularJS使用拦截器实现的loading功能完整实例
May 17 Javascript
详解node单线程实现高并发原理与node异步I/O
Sep 21 Javascript
jQuery实现定时隐藏对话框的方法分析
Feb 12 jQuery
微信小程序页面间传值与页面取值操作实例分析
Apr 30 Javascript
Node如何后台数据库使用增删改查功能
Nov 21 Javascript
vue3.0 上手体验
Sep 21 Javascript
vue技术分享之你可能不知道的7个秘密
Apr 09 #Javascript
一步步教会你微信小程序的登录鉴权
Apr 09 #Javascript
vue组件详解之使用slot分发内容
Apr 09 #Javascript
vue组件中使用props传递数据的实例详解
Apr 08 #Javascript
Vue入门之animate过渡动画效果
Apr 08 #Javascript
vue组件与复用详解
Apr 08 #Javascript
vue使用vue-i18n实现国际化的实现代码
Apr 08 #Javascript
You might like
PHP超全局数组(Superglobals)介绍
2015/07/01 PHP
使用PHP similar text计算两个字符串相似度
2015/11/06 PHP
php中遍历二维数组并以表格的形式输出的方法
2017/01/03 PHP
php利用fsockopen GET/POST提交表单及上传文件
2017/05/22 PHP
PHP实现可精确验证身份证号码的工具类示例
2018/05/31 PHP
ThinkPHP5框架实现简单的批量查询功能示例
2018/06/07 PHP
ext 同步和异步示例代码
2009/09/18 Javascript
基于jquery的tab切换 js原理
2010/04/01 Javascript
jQuery.ajax 用户登录验证代码
2010/10/29 Javascript
js 使用form表单select类实现级联菜单效果
2012/12/19 Javascript
jquery formValidator插件ajax验证 内容不做任何修改再离开提示错误的bug解决方法
2013/01/04 Javascript
Jquery实现带动画效果的经典二级导航菜单
2013/03/22 Javascript
有关于JS构造函数的重载和工厂方法
2013/04/07 Javascript
两种js监听滚轮事件的实现方法
2016/05/13 Javascript
深入理解javascript作用域第二篇之词法作用域和动态作用域
2016/07/24 Javascript
js实现html table 行,列锁定的简单实例
2016/10/13 Javascript
js鼠标跟随运动效果
2017/03/11 Javascript
限时抢购-倒计时的完整实例(分享)
2017/09/17 Javascript
vue.js如何将echarts封装为组件一键使用详解
2017/10/10 Javascript
详解express + mock让前后台并行开发
2018/06/06 Javascript
JS实现的简单分页功能示例
2018/08/23 Javascript
对vuejs的v-for遍历、v-bind动态改变值、v-if进行判断的实例讲解
2018/08/27 Javascript
vue父组件触发事件改变子组件的值的方法实例详解
2019/05/07 Javascript
python验证码识别教程之利用滴水算法分割图片
2018/06/05 Python
Python中垃圾回收和del语句详解
2018/11/15 Python
对Python Class之间函数的调用关系详解
2019/01/23 Python
Python配置虚拟环境图文步骤
2019/05/20 Python
opencv python图像梯度实例详解
2020/02/04 Python
翻转数列python实现,求前n项和,并能输出整个数列的案例
2020/05/03 Python
简单了解Python字典copy与赋值的区别
2020/09/16 Python
某公司面试题
2012/03/05 面试题
师范毕业生自荐信
2013/10/17 职场文书
离婚协议书范本(通用篇)
2014/11/30 职场文书
2015年挂职锻炼工作总结
2014/12/12 职场文书
个人自荐书怎么写
2015/03/26 职场文书
任长霞观后感
2015/06/16 职场文书