Webpack 从哪儿去到哪儿去

流程

指定一个或多个入口(源码目录文件) entry,将各个模块打包封装为一个或多个代码块 chunk,并生成文件一个或多个 bundlecss

entry

肯定入口模块的位置,定义 chunk name,默认为 main。其形式能够是:字符串、对象、数组或函数,字符串和数组其 chunk name 没法改变,只能是默认值。html

字符串入口

module.exports = {
  entry: './src/index.js'
};
复制代码

数组入口

将多个资源先合并,建过最后一个元素做为实际的入口路径。react

module.exports = {
  entry: [
    'babel-polyfill',
    './src/index.js'
  ]
};
复制代码

上面等同于在 ./src/index.jsimport 'babel-polyfill'webpack

对象入口

定义多个入口时必须使用的形式。其中web

  • 对象的属性名 key 就是 chunk name;
  • 对象的属性值 value 就是入口路径,能够是字符串,也能够为数组;
module.exports = {
  entry: {
    'index': ['babel-polyfill', './src/index.js'],
    'lib': './src/lib.js'
  }
};
复制代码

函数式入口

只要返回字符串、数组和对象,能够动态配置,支持返回一个 Promise 对象进行一步操做,自由度很大。数组

module.exports = {
  entry: new Promise((resolve) => {
    // 模拟异步操做
    setTimeout(() => {
      resolve('./src/index.js');
    }, 1000)
  })
};
复制代码

context

资源入口的路径前缀,务必使用绝对路径。其做用是为了让 entry 编写更加简洁。缓存

module.exports = {
  context: path.join(__dirname, './src'),
  entry: './index.js'
}
复制代码

提取 vendor

一般,都是由 app.js 单一入口进行引用,这样就会产生一个 bundle.js 文件,随着业务扩展,资源体积愈加增大,从而下降用户的页面渲染速度。另外,也是因为只产生一个 bundle.js,因此编码稍做改动更新,就用从新打包,用户也要跟着从新下载,友好度不理想。babel

咱们都知道:库、框架等第三方模块(只要是非业务模块)这些几百年不会变化(夸张手法,意在说明不常改动更新),可集中打包。而后客户端缓存起来,从而提升用户界面的渲染速度。react-router

module.exports = {
  entry: {
    app: './src/app.js',
    vendor: ['react', 'react-dom', 'react-router']
  }
};
复制代码

上面 entry 增长了 chunk name 为 vendor 这个 key,其 value 是个数组,可是数组中的值路径并指出,这到底怎么回事?这个就须要 optimization.splitChunks(webpack4 以前是 CommonsChunkPlugin),将 app 和 vendor 这两个 chunk 中的模块提取出来。app

  • app,含业务模块和第三方依赖模块;
  • vendor,第三方模块;

多页应用

咱们但愿的是一个页面对应一个独立的 bundle,而不是将全部页面打包到一个 bundle 中。

module.exports = {
  entry: {
    home: './src/home.js',
    shopCar: './src/shopCar.js',
    order: './src/order.js',
    vendor: ['react', 'react-dom', 'react-router']
  }
}
复制代码

output

说了这么多,都是在说资源入口,对于资源出口使用配置 output 对象,其配置项有不少,在此只举例说明高频使用的一些属性配置。

单入口和多入口

1.单入口

module.exports = {
  output: {
    filename: 'bundle.js',
    path: path.join(__dirname, 'assets'),
    publicPath: '/dist'
  }
};
复制代码

2.多入口

module.exports = {
  entry: {
    app: './src/app.js',
    vendor: './src/vendor.js'
  },
  output: {
    filename: '[name].js'
  }
};
复制代码

filename

打包后的 bundle 名字,可配合 path,也能够是一个相对路径 filename: './src/bundle.js',对于多入口场景能够 filename: [name].js;

变量名称 描述 说明
[hash] 指代 webpack 这次打包全部资源生成的 hash 只要 chunk 内容发生变化,就会改变,影响其余资源
[chunkhash] 指代当前 chunk 内容的 hash 只有当前 chunk 内容发生变化,才会改变,使用缓存推荐使用
[name] 指代当前 chunk 的 name
[id] 指代当前 chunk 的 id
[query] 指代 filename 配置项中的 query 与 chunk 内容无关,需开发者手动指定

因此上面配置能够稍做改动

module.exports = {
  entry: {
    app: './src/app.js',
    vendor: './src/vendor.js'
  },
  output: {
    filename: '[name].[chunkhash].js'
  }
};
复制代码

一般,只有生产环境才配置 [chunkhash],缘由是为了更新缓存,开发环境无需配置。

path

指定资源文件输出位置,其值须为绝对路径,默认为 dist 目录。若是不更改它,可没必要配置;

publicPath

指定资源请求位置,容易与上面 path 的输出位置弄混。请求一种来自 HTML 页面,好比 script 标签加载,一种来自 js 或 css 请求,加载 js、图片或字体等。主要有 3 中形式

1.HTML 形式 相对路径。假设当前 HTML 地址是 http://xxx.com/page/index.html,如今加载 index.js 文件

  • publicPath: '',则 http://xxx.com/page/index.js;
  • publicPath: './js',则 http://xxx.com/page/js/index.js;
  • publicPath: '../assets',则 http://xxx.com/assets/index.js;

2.HOST 形式 相对路径。设置的值如果以 / 开始,就是基于页面地址 host name 为基础路径的。假设当前 HTML 地址是 http://xxx.com/page/index.html,如今加载 index.js 文件

  • publicPath: '/',则 http://xxx.com/index.js;
  • publicPath: '/js/',则 http://xxx.com/js/index.js;
  • publicPath: '/assets/',则 http://xxx.com/assets/index.js;

3.CDN 绝对路径。一般这类资源都是静态的,因为静态资源的域名与当前页面域名不一致,因此才设置指定绝对路径。若 public 值以协议头或相对协议的形式开始,那就说明是与 CDN 相关。

假设当前 HTML 地址是 http://xxx.com/page/index.html,如今加载 index.js 文件

  • publicPath: 'https://cdn.com/',则 https://cdn.com/index.js;
  • publicPath: 'http://cdn.com/',则 http://cdn.com/index.js;
  • publicPath: '//cdn.com/assets/',则 //cdn.com/assets/index.js;

注意,前面咱们介绍的 webpack-dev-server 中也有个 publicPath,比较容易弄混的是 webpack-dev-server 的 publicPath 与 output 的 publicPath没有关系,却与 output 的 path 有关系。可看

module.exports = {
  entry: './src/app.js',
  output: {
    filename: 'bundle.js',
    path: path.join(__dirname, 'dist')
  },
  devServer: {
    publicPath: '/assets/',
    port: 1989
  }
};
复制代码

启动 webpack-dev-server 服务后,访问 localhost:1989/dist/bundle.js 则会返回 404,由于 devServer.publicPath 此时设置的路径是 localhost:1989/assets/,因此访问 localhost:1989/assets/bundle.js 才是有效路径。为了避免必要引发这类麻烦问题,可将二者输出默认设置一致。

上一篇:模块

下一篇:预处理器