webpack概述

若是2020年做为一个前端开发你还不知道 Webpack 是什么,真的就要考虑回炉重造了。不少人可能会得意洋洋,嘴角上扬回答:这谁不知道,不就是一个项目构建工具吗,咱们的项目如今都用着了。这我固然信,可是若是让你认真介绍 Webpack 核心的概念有哪些,底层的原理是怎么样的,那么你还能淡定地娓娓道来吗?以前的我可能也跟大部分人同样,只停留在简单会用,知道的水平,并且几乎每一个经历过的项目也都在使用,也知道 create-react-appvue-cli 底层都是依赖 webpack,可是我以为做为一个想要更进阶的前端工程师,你须要掌握的更多。这也是为何我想写这篇文章的缘由之一,这是也是我从新学习 Webpack 系列的第一篇:Webpack概述。javascript

一句话介绍

先看官网的介绍:css

webpack is a static module bundler for modern JavaScript applications.html

翻译过来大概的意思就是 Webpack 是一个现代的 JavaScript 应用 模块 打包器。首先咱们要清楚它的定位是为 JavaScript 应用 服务的,有时候咱们开发一些组件库、工具库,开发完后也须要有一个打包构建、上线这样一个过程,这种类型的项目咱们通常不用 Webpack,而是用 Rollup 这样的工具。第二,咱们要注意的是,上面我特地加粗的另外一个关键词:模块。那么在 Webpack 眼里到底哪些是模块?前端

一切皆模块

随着 Commonjs 的出现,CMDAMD 模块思想的诞生,ES Module 逐渐成为标准, JavaScript 终于进入了模块化编程的时代。模块化编程使得咱们更好的组织JS代码,合理的划分也使得代码更容易调试、测试。NodeJS诞生的时候就有本身的模块化,而Web的模块进展一直比较缓慢。与Node.js模块相比,webpack模块能够用多种方式表达模块之间的依赖关系。下面是一些例子:vue

  • ES2015 import
  • CommonJS require()
  • AMD的 definerequire
  • css/sass/less 文件中的 @import
  • 样式文件中的图片 url(...) 和 HTML 中的<img src="...">

Webpack 也支持各类各样的模块,下面是一些经常使用的例子:java

  • TypeScript
  • ESNext
  • Sass
  • Less
  • Stylus
  • Vue
  • ...

咱们知道 Webpack 主要是一个 JavaScript 的打包器,那么它怎么识别和处理其它的非JS模块呢?这就牵涉到 Webpack 最重要的概念: Loader,下面咱们开始介绍 Webpack 的核心概念。react

核心概念


Entry

入口代表了 Webpack 从哪一个模块开始构建内部的依赖图,Webpack 将找出入口所依赖的其它模块和库。它的默认值是 src/index.js,你也能够经过配置指定不一样的路径:webpack

module.exports = {
  entry: './path/to/my/entry/file.js'
};
复制代码

你也能够配置多个入口,在开发多页面应用的时候就可能须要配置多个入口:web

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

Output

既然有入口,那就有出口,出口选项告诉 Webpack 构建好的 bundles 放在哪一个目录下以及怎么命名输出的文件。默认值是:./dist/main.js,输出的文件默认都放在 dist 目录下。固然你也能够自定义本身的 output 选项:正则表达式

const path = require('path');

module.exports = {
  entry: './path/to/my/entry/file.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'my-first-webpack.bundle.js'
  }
};
复制代码

在上面的例子中,output.path 告诉 Webpack 输出的文件放在什么目录下,output.filename 指明生成的文件命名规则。

Loaders

前面咱们提到了一切资源(字体文件、图片、CSS、预编译器Sass等)甚至 Vue 组件在 Webpack 中都被当成模块来处理,可是 Webpack 自身其实只是一个 JavaScript Bundler ,它只认识JS模块和JSON文件。因为在一个复杂的Web应用中,咱们不仅有JS模块,也有HTML、CSS、图片等资源,若是使用框架,还须要 Vue SFCReact jsx等,因此这时候就须要 Loaders 出马了。Loaders 可使得 Webpack 可以处理各类类型的模块,处理完后再把它们加入到依赖图中。

每一个 loader 配置主要有两个选项:

  • test 选项,确认哪些些文件将被 loader 转换,通常是一个正则表达式;
  • use 选项,代表哪些 loaders 将被用来转换文件。

下面看一个例子:

module.exports = {
  output: {
    filename: 'my-first-webpack.bundle.js'
  },
  module: {
    rules: [
      { test: /\.js$/, use: 'babel-loader' }
    ]
  }
};
复制代码

上面的例子,定义了一个 loader 转换规则,它告诉 Webpack 编译器,当发现js 文件的时候,使用 babel-loader 进行转换。

咱们还能够配置多个 loader,好比下面这个例子:

module.exports = {
  module: {
    rules: [
      {
        test: /\.scss$/,
        use: [
          // style-loader
          { loader: 'style-loader' },
          // css-loader
          {
            loader: 'css-loader',
            options: {
              modules: true
            }
          },
          // sass-loader
          { loader: 'sass-loader' }
        ]
      }
    ]
  }
};
复制代码

上面这个例子告诉 Webpack 编译器,当遇到以 .scss 结尾的文件,先用 sass-loader 处理,接着再用 css-loader 转化,最后使用 style-loader 完成此类文件的处理,它的处理顺序是从后往前。

Plugins

Loaders 帮助 Webpack 处理不一样类型的文件和模块,而插件被用来扩展 Webpack 的功能,使得Webpack 更增强大,插件能够用来优化 bundle(压缩文件、tree shaking、code split等)、管理静态资源和注入环境变量。

使用一个插件以前,首先经过 require 引入插件,而后将它添加到 plugins 选项数组中,大部分插件支持一些选项配置。因为能够在配置中为不一样的需求屡次使用插件,因此你须要经过使用new操做符调用插件来建立它的实例:

const HtmlWebpackPlugin = require('html-webpack-plugin'); //installed via npm

module.exports = {
  module: {
    rules: [
      { test: /\.txt$/, use: 'raw-loader' }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({template: './public/index.html'})
  ]
};
复制代码

在上面的例子中,html-webpack-plugin 将会为你的应用生成一个 html 文件,而且这个文件会被自动注入 Webpack 处理生成的全部 bundle

Webpack 中配置插件仍是比较简单的,关键是你要了解生态中有哪些优秀的插件能够直接拿来使用,挑选出适合你本身项目的插件组合,在没有合适的插件支撑你的业务需求时,你也选择能够开发本身的 Webpack 插件。

以上是我以为在 Webapck 中比较核心的概念,这些是你学习 Webpack 必须掌握的概念,EntryOutput 可能相对简单,LoadersPlugins 机制是核心中的核心,其底层的原理也值得仔细探究,后续的文章中我会对其进行分析。

补充

在官方文档中,还提到两个点能够注意一下。一个是 mode,经过设置不一样的值,告诉 Webpack 当前是开发环境仍是生产环境。其主要的值有 developmentproductionnone,对于每一个选项, Wepack 都会在底层作相应环境的一些优化,它的默认值是:production

第二个点是 Browser Compatibility,也就是浏览器兼容性。webpack支持全部兼容es5的浏览器(不支持IE8及如下版本)。Webpack 中的 import()require.ensure() 须要支持Promise,若是你想支持较老的浏览器,须要 引入 Polyfill ,想要了解更多,能够查看:load polyfill

相关文章
相关标签/搜索