webpack4.0 基础准备

webpack官方文档地址链接 ,本文主要介绍开始webpack前的准备工作。

  • 前言

为什么要引入webpack

  随着前端工程越来越复杂,单独创建html js css的方式已经无法保证项目的可维护性,所以我们就需要考虑把不同的业务逻辑拆分成模块,然后分开引入这些模块,每个模块做自己的事情,这样就可以保证项目的可维护性和可扩展性了。假如我们一个复杂的工程需要几千个js文件,我们不可能引入几千个js文件,所以我们需要借助工具来管理模块,目前使用率最高的有webpackGRUNTGulpBrowserify,并且Vue,React,Angular脚手架都开始使用webpack做底层框架,主要得益于它的Tree Shaking 代码懒加载 代码分割 等特性。

什么是webpack

  官方介绍:webpack是一个现代 JavaScript应用程序的静态模块打包器(module bundler)。当 webpack处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。核心定义为:‘模块打包工具’。那么,在了解webpack之前,首先要清楚什么是模块,如何使用模块。

什么是modules

  在模块化编程中,开发者将程序分解成离散功能块(discrete chunks of functionality),并称之为模块
  每个模块具有比完整程序更小的接触面,使得校验、调试、测试轻而易举。 精心编写的模块提供了可靠的抽象和封装界限,使得应用程序中每个模块都具有条理清楚的设计和明确的目的。
  以上是官方的介绍,以我自己的理解,程序我可以理解为车轮,我们都知道,车轮有轮胎和轮毂,那么轮胎的生产线生产轮胎这个零件,轮毂的生产线生产轮毂这个零件,各自分工互不打扰,那么轮胎和轮毂的生产线我们可以理解为模块,而产出的轮胎和轮毂我们可以理解为模块的方法,而生产出轮胎和轮毂的过程我们可以理解为导出,而车间人员拿过来组装的过程我们可以理解为导入。


常见的webpack modules

   ES ModuleCommonJSCMDAMD、 css/sass/less 文件中的 @import 语句...

相关modules使用方法

  • Es Module

export 默认导出整个模块,或具名导出模块

// 具名导出
export let Hello = 'Echonessy';
export const Word = () => {  return ‘Boy’; }

// 默认导出
export default {
  Hello,Word
}

import通过 import 以静态的方式,导入另一个通过 export 导出的模块。

//  具名导出的引用
import { Hello,Word } from './hello-word.js';
// 使用方式
Hello;
Word();

//  默认导出的引用 HelloWord 包含Hello、Word两个对象
import HelloWord from './hello-word.js';
// 使用方式
HelloWord.Hello;
HelloWord.Word();
  • export导出多个对象,export default只能导出一个对象并且一个文件里只能有一个。
  • export导出对象需要用{ },export default不需要{ }
export {A,B,C};
export default A;

import()动态地加载模块。调用 import()之处,被作为分离的模块起点,意思是,被请求的模块和它引用的所有子模块,会分离到一个单独的 chunk 中。

import规范不允许控制模块的名称或其他属性,因为 "chunks" 只是 webpack中的一个概念。幸运的是,webpack中可以通过注释接收一些特殊的参数,而无须破坏规定,具体参数介绍请参考官方文档

import(
   /* webpackChunkName: "newChunkName" */
   /* webpackMode: "lazy" */
    './hello-word.js'
).then(HelloWord =>{
      HelloWord.Hello;
      HelloWord.Word();
    }).catch(e => { })
  • CommonJS

require以同步的方式检索其他模块的导出。由编译器(compiler)来确保依赖项在最终输出 bundle 中可用。对应的导出方法为exportsmodule.exports

const HelloWord = require('HelloWord');

exportsmodule.exports:一个模块被引用的时候最终都会被输出成module.exports,而exports只是module.exports的一个引用

const helloWord = require('../controllers/helloWord');
module.exports = helloWord;
console.log(module)
// 控制台打印如下
Module {
  id: 'E:\\ExpServer\\routes\\index.js',
  exports: { Hello: [Function] }
  ...
  }

require.resolve以同步的方式获取模块的 ID。由编译器(compiler)来确保依赖项在最终输出 bundle 中可用。更多关于模块的信息,请点击这里 module.id。使用require.resolve函数查询模块文件名时并不会加载该模块。

module.id === require.resolve("./HelloWord.js")

require.cache多处引用同一个模块,最终只会产生一次模块执行和一次导出。所以,会在运行时(runtime)中会保存一份缓存。删除此缓存,会产生新的模块执行和新的导出。

require.cache[module.id] === module

require.ensure()是 webpack 特有的,已经被 import() 取代。

  • webpack 特定的方法

require.context()使用 directory 路径、includeSubdirs 选项和 filter 来指定一系列完整的依赖关系,便于更细粒度的控制模块引入。
当我们需要引入某一目录下多个文件的时候,一个一个的导入似乎会显得非常麻烦,这里我们就可以考虑使用此方法获取该目录下的文件,通过提取注入到一个文件里。

require.context(directory:String, includeSubdirs:Boolean /* 可选的,默认值是 true */, filter:RegExp /* 可选的 */);

require.include引入一个不需要执行的依赖,这可以用于优化输出 chunk中的依赖模块的位置。

require.include(dependency: String)

webpack 环境搭建

准备工作:nodeJs ,这里我们最好安装最新版本的,因为会提升webpack打包速度,
下载下来之后,傻瓜式安装完成之后打开CMD输入以下指令

G:\Echonessy>node -v
v10.16.3

G:\Echonessy>npm -v
6.9.0

这样说明nodenpm安装完毕

接下来我们新建一个文件夹,作为我们webpack的工程目录webpackDemo,我们通过npm进行初始化,让它符合webpack的使用环境具体指令

G:\Echonessy\webpack>cd webpackDemo

G:\Echonessy\webpack\webpackDemo>npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.

See `npm help json` for definitive documentation on these fields
and exactly what they do.

Use `npm install <pkg>` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
package name: (webpackdemo)
version: (1.0.0)
description: this is a demo
entry point: (index.js)
test command:
git repository:
keywords:
author: Echonessy
license: (ISC)
About to write to G:\Echonessy\webpack\webpackDemo\package.json:

{
  "name": "webpackdemo",
  "version": "1.0.0",
  "description": "this is a demo",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Echonessy",
  "license": "ISC"
}


Is this OK? (yes) yes

接下来我们就会发现文件夹里多了一个package.json文件


初始化完成之后,那么接下来开始安装webpack(注,webpack可能会出现安装失败的情况,这里是由于webpack源会被国内强掉,这里可以通过手机热点来连接WIFI安装),我们首先进入webpackDemo这个目录下


//  项目内安装webpack(建议)
npm install webpack webpack-cli -D 

G:\Echonessy\webpack\webpackDemo>npm install webpack webpack-cli -D
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN webpackdemo@1.0.0 No repository field.
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.9 (node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.9: 
wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})

+ webpack-cli@3.3.7
+ webpack@4.39.2
added 385 packages from 218 contributors and audited 5286 packages in 441.279s
found 0 vulnerabilities

// 查看版本  npx 想要解决的主要问题,就是调用项目内部安装的模块
G:\Echonessy\webpack\webpackDemo>npx webpack -v
4.39.2



//  全局安装webpack(不建议,因为如果存在多个项目假如各项目webpack版本不同,会有问题)
npm install webpack webpack-cli -g

webpack 配置

webpack的打包文件为webpack.config.jswebpack默认内部有打包配置,如果找不到配置文件会执行内部默认配置。

G:\Echonessy\webpack\webpackDemo>npx webpack index.js
Hash: 53742f9efd12248f7206
Version: webpack 4.39.2
Time: 941ms
Built at: 2019-08-21 2:40:55 PM
  Asset      Size  Chunks             Chunk Names
main.js  5.09 KiB       0  [emitted]  main
Entrypoint main = main.js
[0] ./index.js 365 bytes {0} [built]
    + 2 hidden modules

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/configuration/mode/

默认会把index.js文件打包成main.js并且存放在dist文件夹下
那么如何配置我们自定义的规则?

这里我们新建一个index.js作为需要打包的文件
新建一个webpack.config.js配置文件

image.png

那么接下来我们需要在配置文件里去配置我们需要打包的规则
打开webpack.config.js配置文件

const path = require('path');

module.exports = {
    //两种模式  development 代码不会被压缩  production会被压缩
    mode: 'development',   
    //入口
    entry: './index.js', // 我们需要打包的文件
    //出口
    output:{
        filename:'outBundle.js',// index.js打包后的文件名字
        path: path.resolve(__dirname,'bundle'),//index.js打包后所在的文件夹
    }
}

执行打包配置

G:\Echonessy\webpack\webpackDemo>npx webpack
Hash: b82930305775bdc66443
Version: webpack 4.39.2
Time: 650ms
Built at: 2019-08-21 2:50:15 PM
       Asset       Size  Chunks             Chunk Names
outBundle.js  930 bytes       0  [emitted]  main
Entrypoint main = outBundle.js
[0] ./index.js 49 bytes {0} [built]


这里我们会发现,我们的工程多出了一个文件夹bundle文件夹,里面有个outBundle.js

image.png

那么问题来了,这个配置文件我想自己命名,并且放到配置文件目录里,这个时候打包的时候该怎么办?

这里我把webpack.config.js重命名为webpackConfig.js并且放在config文件夹下面

image.png

这里,我们就需要通过命令指定配置文件去打包,我们进入到config目录下通过--config 指向webpackConfig.js,这样就可以打包成功了。

const path = require('path');

module.exports = {
    mode: 'development',
    //入口
    entry: '../index.js', // 我们需要打包的文件
    //出口
    output:{
        filename:'newOutBundle.js',// index.js打包后的文件名字
        path: path.resolve(__dirname,'../newBundle'),//index.js打包后所在的文件夹
    }
}


G:\Echonessy\webpack\webpackDemo\config>npx webpack --config webpackConfig.js
Hash: b82930305775bdc66443
Version: webpack 4.39.2
Time: 186ms
Built at: 2019-08-21 3:02:21 PM
          Asset       Size  Chunks             Chunk Names
newOutBundle.js  930 bytes       0  [emitted]  main
Entrypoint main = newOutBundle.js
[0] ../index.js 49 bytes {0} [built]

G:\Echonessy\webpack\webpackDemo\config>

以上打包每次都需要用npx webpack 这种固定语法去打包我们的文件,那么问题来了,这指令我们可不可以自定义?我们都知道,vue有两种我们常用的指令,一个是npm run dev一个是npm run build,那么我们是否可以创建我们自己的指令?答案是肯定的

首先,我们打开package.json 会有个scripts对象 这里我们新建一个指令,取名为setup,执行的语句为webpack

{
  "name": "webpackdemo",
  "version": "1.0.0",
  "description": "this is a demo",
  "main": "index.js",
  "scripts": {
    "setup": "webpack"
  },
  "author": "Echonessy",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^4.39.2",
    "webpack-cli": "^3.3.7"
  }
}

执行后你会发现
npx webpack == npm run setup


实例1:

我们都知道,浏览器是不能直接运行es6的相关语法的,那么,如果我们要运行,该怎么处理?其实webpack还可以进行代码的简单 '翻译'。

这里我们实现一个简单的需求,就是我们有两个模块,分别对应AB,将AB通过模块的内容通过导入导出方式显示在页面上。

这里我们新建个文件夹src用来存放我们的源代码

image.png

我们新建一个a.js

export const A = () => {
    return "I'm A";
}

我们新建一个b.js

export const B = () => {
    return "I'm B";
}

新建一个index.js作为模块引入文件

import { A } from './a.js'
import { B } from './b.js'
document.getElementById('main').innerHTML = A() + '</br>' + B();

同样的,我们需要创建一个index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="main"></div>
<script src="./index.js"></script>
</body>
</html>

我们直接运行,可以看到,浏览器控制台会报index.js的语法错误,并且,我们的页面也没有显示任何东西。

image.png

那么这里我们创建一个webpack配置文件 将我们的index.js打包出来

const path = require('path');
module.exports = {
    mode: 'production',
    //入口
    entry: './src/index.js', // 我们需要打包的文件
    //出口
    output:{
        filename:'newIndex.js',// index.js打包后的文件名字
        path: path.resolve(__dirname,'newDist'),//index.js打包后所在的文件夹
    }
}

我们执行在工程目录下执行

npx webpack src/index.js

或者执行我们自定义的指令

G:\Echonessy\webpack\webpackDemo>npm run setup

> webpackdemo@1.0.0 setup G:\Echonessy\webpack\webpackDemo
> webpack

Hash: e4f933d03797360cf137
Version: webpack 4.39.2
Time: 162ms
Built at: 2019-08-21 4:19:06 PM
      Asset        Size  Chunks             Chunk Names
newIndex.js  1010 bytes       0  [emitted]  main
Entrypoint main = newIndex.js
[0] ./src/index.js + 2 modules 373 bytes {0} [built]
    | ./src/index.js 173 bytes [built]
    | ./src/a.js 100 bytes [built]
    | ./src/b.js 100 bytes [built]

这样我们新的index.js打包文件就打包完成了,接下来,我们更改index.htmljs引入路径

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="main"></div>
<script src="../newDist/newIndex.js"></script>
</body>
</html>

我们再次打开浏览器,发现我们想要的效果出来了


image.png
以上是相关简单的webpack介绍和基础使用方法,后续会持续更新其他相关的用法......
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,716评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,558评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,431评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,127评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,511评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,692评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,915评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,664评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,412评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,616评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,105评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,424评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,098评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,096评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,869评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,748评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,641评论 2 271

推荐阅读更多精彩内容