Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

webpack实战(0-1)-入门配置 #14

Open
liujie2019 opened this issue Mar 3, 2019 · 0 comments
Open

webpack实战(0-1)-入门配置 #14

liujie2019 opened this issue Mar 3, 2019 · 0 comments

Comments

@liujie2019
Copy link
Owner

[TOC]

1. 模块化

模块化是指将一个复杂的系统分解为多个模块以方便编码。

1.1 CommonJS

CommonJS是一种被广泛使用的javascript模块化规范,其核心思想是:通过require方法来同步加载依赖的其他模块,通过module.exports导出需要暴露的接口。CommonJS规范的流行得益于Node.js采用了这种方式,后来这种方式被引入到了网页开发中。

// 导入
const moduleA = require('./moduleA');
// 导出
module.exports = moduleA.someFunc;

CommonJS的优点:

  • 代码可复用于Node.js环境下并运行,例如做同构应用;
  • 通过Npm发布的很多第三方模块都采用了CommonJS规范。

CommonJS的缺点:这样的代码无法直接运行在浏览器环境下,必须通过工具转换成标准的ES5。

1.2 AMD

AMD也是一种javascript模块化规范,与CommonJS最大的不同在于:它采用了异步的方式去加载依赖的模块。AMD规范主要用于解决针对浏览器环境的模块化问题,最具代表性的实现是requirejs

// 定义一个模块
define('module', ['dep'], function(dep) {
    return exports;
});
// 导入和使用
require(['module'], function(module) {
});

AMD的优点:

  1. 可在不转换代码的情况下直接在浏览器中运行;
  2. 可异步加载依赖;
  3. 可并行加载多个依赖;
  4. 代码可运行在浏览器环境和Node.js环境下。

AMD的缺点:在javascript运行环境没有原生支持AMD,需要先导入实现了AMD的库后才能正常使用。

1.3 ES6模块化

ES6模块化是国际标准化组织ECMA提出的javascript模块化规范,它在语言层面上实现了模块化。浏览器厂商和Node.js都宣布要原生支持该规范,它将逐渐取代CommonJS和AMD规范,成为浏览器和服务器通用的模块化解决方案。

// 导入
improt React, {Component} from 'react';
// 导出
export function hello() {};
export default {
 // ...
}

ES6模块化虽然是终极模块化方案,但是它的缺点在于:目前无法直接运行在大部分javascript运行环境下,必须通过工具转换成标准的ES5后才能正常运行。

Webpack 2版本开始,Webpack已经内置了对ES6、CommonJS、AMD模块化语句的支持。

2. 安装webpack

2.1 安装webpack到全局
npm i -g webpack webpack-cli
2.2 安装webpack到项目目录
// 安装最新的稳定版本
npm i -D webpack webpack-cli
// 安装指定版本
npm i -D webpack@<version> webpack-cli@<version>
// 安装最新的体验版本
npm i -D webpack@beta webpack-cli@beta

特别注意:一般不推荐全局安装webpack,原因是可防止不同的项目因依赖不同版本的webpack而导致冲突。

3. webpack使用

在编写webpack代码之前,先搭建如下的项目目录:

webpack-demo             # 项目名
|   |--- dist            # 打包后生成的文件目录             
|   |--- node_modules    # 所有的依赖包
|   |--- src             # 项目源码目录
|   | |-- js             # js文件目录
|   | |-- styles         # css文件目录
|   |--- webpack.config.js # webpack配置文件
|   |--- index.html       # html文件                     
|   |--- .gitignore  
|   |--- README.md
|   |--- package.json

3. 使用Loader

// 安装loader
npm i -D style-loader css-loader
module: {
    rules: [
        {
            test: /\.css$/,
            use: ['style-loader', 'css-loader?minimize']
        }
    ]
}
  • use属性的值是一个由Loader名称组成的数组,Loader的执行顺序是由后到前的;
  • 每个Loader都可以通过URL querystring的方式传入参数,例如上述代码中'css-loader?minimize'中的minimize就是告诉css-loader要开启css压缩。

loader传入属性的方式除了可以通过URL querystring实现,还可以通过Object实现,配置如下:

module: {
    rules: [
        {
            test: /\.css$/,
            use: ['style-loader',
                {
                    loader: 'css-loader',
                    // 设置loader相关参数
                    options: {
                        minimize: true
                    }
                }
            ]
        }
    ]
}

style-loader的工作原理是:将css的内容用javascript里的字符串存储起来,在网页执行javascript时通过DOM操作,动态地向HTML head标签里插入HTML style标签。

4. 使用Plugin

Plugin是用来扩展webpack功能的,通过在构建流程里注入钩子实现,为webpack带来了很大的灵活性。
如果想要使用一个插件,我们只需要require()它,然后把它添加到plugins数组中。我们可以在一个配置文件中因为不同的目的多次使用用一个插件,因此我们可以使用new操作符来创建它的实列。

mini-css-extract-plugin是将css提取到单独文件中的插件,具体配置如下:

npm install --save-dev mini-css-extract-plugin
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      // 指定提取出来的css文件的名称
      filename: "[name]_[contenthash:8].css"
    })
  ],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          "css-loader"
        ]
      }
    ]
  }
}

[name]代表文件的名称,[contenthash:8]代表根据文件内容算出的8位Hash值。

5. 使用DevServer(端口号默认是8080)

DevServer会启动一个HTTP服务器用于服务网页请求,同时会帮助启动Webpack,并接收Webpack发出的文件变更信号,通过WebSocket协议自动刷新网页做到实时预览。

npm i -D webpack-dev-server

需要注意的是:DevServer会将Webpack构建出的文件保存在内存中,在要访问输出的文件时,必须通过HTTP服务访问。

5.1 实时预览

Webpack在启动时可以开启监听模式,默认是关闭的,之后Webpack会监听本地文件系统的变化,在发生变化时重新构建出新的结果。Webpack默认关闭监听模式,我们可以在启动Webpack时通过如下命令来开启监听模式:

webpack --watch

通过DevServer启动的Webpack会开启监听模式,当发生变化时重新执行构建,然后通知DevServerDevServer会让Webpack在构建出的javascript代码里注入一个代理客户端用于控制网页,网页和DevServer之间通过WebSocket协议通信,以方便DevServer主动向客户端发送命令。DevServer在收到来自Webpack的文件变化通知时,通过注入的客户端控制网页刷新

如果尝试修改index.html文件并保存,则我们会发现这并不会触发以上机制,导致这个问题的原因是:Webpack在启动时会以配置里的entry为入口去递归解析出entry所依赖的文件,只有entry本身和依赖的文件才会被Webpack添加到监听列表里。而index.html文件是脱离了javascript模块化系统的,所以Webpack不知道它的存在。但是要完成上面的实时预览,html页面的bundle.js要直接引入即可,如下html页面代码:

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

为什么http://localhost:8080/bundle.js这样也能访问的到呢?原因是:DevServer会将webpack构建出的文件保存在内存中,DevServer不会理会webpack.config.js里配置的output.path属性的。

5.2 模块热替换

除了上面介绍的改动本地入口文件或依赖文件后,会自动打包,然后会自动刷新浏览器即可看到更新效果外,我们还可以使用模块热替换技术,

模块热替换技术能做到在不重新加载整个网页的情况下,通过将已更新的模块替换旧模块,它默认是关闭的,要开启模块热替换,我们只需在启动DevServer时带上--inline参数即可。如下命令:

webpack-dev-server --inline  
webpack-dev-server --inline --hot

webpack-dev-server有如下两种启动模式:

  1. iframe:该模式下修改代码后会自动打包,但是浏览器不会自动刷新;
  2. inline:内联模式,该模式下修改代码,webpack将自动打包并刷新浏览器。
5.3 支持Source Map

在浏览器中运行javascript代码都是编译器输出的代码,但是如果在代码中碰到一个bug的时候,我们不好调式,因此我们需要Source Map来映射到源代码上,Webpack支持生成Source Map,只需在启动时带上--devtool source-map参数即可;如下命令:

webpack-dev-server --inline --hot --devtool source-map

注意:每次运行如上命令,感觉非常长,因此我们可以在项目的根目录的package.json文件的scripts中添加如下配置:

"scripts": {
  "dev": "webpack-dev-server --devtool source-map --hot --inline"
}

加上如上配置后,我们只需要在命令行中运行npm run dev即可;

其他配置常见的选项:

  • --quiet:控制台中不输出打包的信息;
  • --compress:开启gzip的压缩;
  • --progress:显示打包的进度。

因此在项目中scripts经常会做如下配置:

"scripts": {
  "dev": "webpack-dev-server --progress --colors --devtool source-map --hot --inline",
  "build": "webpack --progress --colors"
}

这样的话,打包的时候会显示打包进度。

也可以在webpack.config.js中添加如下配置:

// 开启Source Map
devtool: 'cheap-module-source-map'

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Webpack
Webpack实战
Development

No branches or pull requests

1 participant