webpack中的module、chunk和bundle的区别:css
module、chunk 和 bundle 其实就是同一份逻辑代码在不一样转换场景下的取了三个名字,咱们直接写出来的是 module,webpack 处理时是 chunk,最后生成浏览器能够直接运行的 bundle。html
通常来讲一个 chunk 对应一个 bundle,好比上图中的 utils.js -> chunks 1 -> utils.bundle.js
;但咱们也能够用一些插件进行文件分离,好比说上图中,就用 MiniCssExtractPlugin
插件从 chunks 0 中抽离出了 index.bundle.css
文件。vue
参考:https://www.cnblogs.com/skychx/p/webpack-module-chunk-bundle.htmlnode
在使用 webpack 构建的典型应用程序或站点中,有三种主要的代码类型:react
runtime 以及伴随的 manifest 数据,主要是指:在浏览器运行过程当中,webpack 用来链接模块化应用程序所需的全部代码。它包含:在模块交互时,链接模块所需的加载和解析逻辑。包括:已经加载到浏览器中的链接模块逻辑,以及还没有加载模块的延迟加载逻辑。webpack
webpack 和 webpack 插件是如何“知道”应该哪些文件生成的呢?答案是,webpack 经过 manifest,能够追踪全部模块到输出 bundle 之间的映射。在你的应用程序中,形如 index.html
文件、一些 bundle 和各类资源,都必须以某种方式加载和连接到应用程序,一旦被加载到浏览器中。在通过打包、压缩、为延迟加载而拆分为细小的 chunk 这些 webpack 优化
以后,你精心安排的 /src
目录的文件结构都已经再也不存在。因此 webpack 如何管理全部所需模块之间的交互呢?这就是 manifest 数据用途的由来。git
当 compiler 开始执行、解析和映射应用程序时,它会保留全部模块的详细要点。这个数据集合称为 "manifest",当完成打包并发送到浏览器时,runtime 会经过 manifest 来解析和加载模块。不管你选择哪一种 模块语法,那些 import
或 require
语句如今都已经转换为 __webpack_require__
方法,此方法指向模块标识符(module identifier)。经过使用 manifest 中的数据,runtime 将可以检索这些标识符,找出每一个标识符背后对应的模块。es6
经过使用内容散列(content hash)做为 bundle 文件的名称,这样在文件内容修改时,会计算出新的 hash,浏览器会使用新的名称加载文件,从而使缓存无效。一旦你开始这样作,你会当即注意到一些有趣的行为。即便某些内容明显没有修改,某些 hash 仍是会改变。这是由于,注入的 runtime 和 manifest 在每次构建后都会发生变化。github
Babel实际上是一个编译JavaScript的平台,它能够编译代码帮你达到如下目的:web
Babel实际上是几个模块化的包,其核心功能位于称为babel-core
的npm包中,webpack能够把其不一样的包整合在一块儿使用,对于每个你须要的功能或拓展,你都须要安装单独的包.
用得最多的是解析Es6的babel-preset-
包和解析JSX的babel-preset-react
包。
下面测试使用 babel 来解析支持 es6 和 react 语法。咱们先来一次性安装这些依赖包:
// npm一次性安装多个依赖模块,模块之间用空格隔开 npm install --save-dev babel-core babel-loader babel-preset-env babel-preset-react
在webpack
中配置Babel的方法以下:
module.exports = {
entry: __dirname + "/app/main.js",//已屡次说起的惟一入口文件
output: { path: __dirname + "/public",//打包后的文件存放的地方 filename: "bundle.js"//打包后输出文件的文件名 }, devtool: 'eval-source-map', devServer: { contentBase: "./public",//本地服务器所加载的页面所在的目录 historyApiFallback: true,//不跳转 inline: true//实时刷新 }, module: { rules: [ { test: /(\.jsx|\.js)$/, use: { loader: "babel-loader", options: { presets: [ "env", "react" ] } }, exclude: /node_modules/ } ] } };
配置完以上选项后就能支持ES6以及JSX的语法了。测试:
npm install --save react react-dom
//Greeter,js
import React, {Component} from 'react'
import config from './config.json'; class Greeter extends Component{ render() { return ( <div> {config.greetText} </div> ); } } export default Greeter
// main.js
import React from 'react';
import {render} from 'react-dom'; import Greeter from './Greeter'; render(<Greeter />, document.getElementById('root'));
直接编译或者在本地服务器上就能看到运行结果
Babel其实能够彻底在 webpack.config.js
中进行配置,可是考虑到babel具备很是多的配置选项,在单一的webpack.config.js
文件中进行配置每每使得这个文件显得太复杂,所以一些开发者支持把babel的配置选项放在一个单独的名为 ".babelrc" 的配置文件中。webpack会自动调用.babelrc
里的babel配置选项
module.exports = {
entry: __dirname + "/app/main.js",//已屡次说起的惟一入口文件
output: { path: __dirname + "/public",//打包后的文件存放的地方 filename: "bundle.js"//打包后输出文件的文件名 }, devtool: 'eval-source-map', devServer: { contentBase: "./public",//本地服务器所加载的页面所在的目录 historyApiFallback: true,//不跳转 inline: true//实时刷新 }, module: { rules: [ { test: /(\.jsx|\.js)$/, use: { loader: "babel-loader" }, exclude: /node_modules/ } ] } };
//.babelrc
{
"presets": ["react", "env"] }
因为以前的一些编译可能会致使用于输出的文件夹中包含了一些不必的文件,显得比较杂乱,咱们能够用clean-webpack-plugin
插件清理输出的文件夹中的文件。
该插件会在每次构建前清理输出文件夹,只会生成用到的文件。
npm install clean-webpack-plugin --save-dev
const path = require('path');
const CleanWebpackPlugin = require('clean-webpack-plugin'); module.exports = { entry: { app: './src/index.js', print: './src/print.js' }, plugins: [ new CleanWebpackPlugin(['public/*.*'], { root: __dirname, verbose: true, //开启在控制台输出信息 dry: false }) ], output: { filename: '[name].bundle.js', path: path.resolve(__dirname, 'dist') } };
有一个问题是当热加载和CleanWebpackPlugin插件同时使用时,运行dev-sever会从新编译,由此也从新使用清理插件,目标文件夹中的文件将被所有删除,可是此时并不生成新的文件。
虽然没报什么问题,代码也能够跑,可是仍是困惑了我好久。这个问题应该是运行webpack-dev-server时webpack会从新编译,由此使用了清理插件,可是dev-server并不会在工做目录中生成编译的文件,而是在内存中生成,因此看不到,可是代码跑的没问题。
要想解决这个问题,我在GitHub上看到了一个issue,可是尝试了好像会报错:https://github.com/johnagan/clean-webpack-plugin/issues/96。事后会继续关注该问题。
这些选项能设置模块如何被解析。
在咱们引入一些模块文件时,可能文件路径层次比较深,这样的话就会致使相对路径的写法比较长。经过 resolve.alias 可以将一些路径配置成指定的别名,可以让咱们简写路径。
module.exports = { ... resolve: { alias: { 'vue$': 'vue/dist/vue.esm.js', '@': resolve('src'), //由此引入src文件夹下的文件就能够写成:import xxx from @/xxx.js } }, }
经过指定 resolve 字段的extensions值能够指定自动解析的文件扩展名。
webpack的默认配置为:
module.exports = { //... resolve: { extensions: ['.wasm', '.mjs', '.js', '.json'] } };
由此用户在引入模块一些文件时就能够不带扩展,好比:
//引入 mian.js import aaa from '../path/to/main';
若是咱们自定义该选项,就会覆盖默认数组即webpack的默认配置,这就意味着 webpack 将再也不尝试使用默认扩展来解析模块,对于须要指定自动解析的文件扩展名必须得写入该数组中。
告诉 webpack 解析模块时应该去哪一个目录搜索该模块。
webpack的默认配置为:
module.exports = { //... resolve: { modules: ['node_modules'] } };
webpack-dev-server 可以用于快速开发应用程序。