Webapck 简单配置

580 阅读4分钟

核心概念

webpack是一个应用程序的静态模块打包工具,当webpack处理应用程序时,它会在内部构建一个依赖图:

任何时候,一个文件依赖于另一个文件,webpack 就把此视为文件之间有 依赖关系。这使得 webpack 可以接收非代码资源(non-code asset)(例如 images 或 web fonts),并且可以把它们作为 依赖 提供给你的应用程序。

此依赖图会映射项目所需的每一个模块,并生成一个或多个bundle。

特点

  • 代码转换: TypeScript 编译成 JavaScript、SCSS,LESS 编译成 CSS.
  • 文件优化:压缩 JavaScript、CSS、HTML 代码,压缩合并图片。
  • 代码分割:提取多个页面的公共代码、提取首屏不需要执行部分的代码让其异步加载。
  • 模块合并:在采用模块化的项目里会有很多个模块和文件,需要构建功能把模块分类合并成一个文件。
  • 自动刷新:监听本地源代码的变化,自动重新构建、刷新浏览器。
  • 自动化流程

入口(entry)

入口起点指示 webpack 应该使用哪个模块,来作为构建其内部 依赖图的开始。进入入口起点后,webpack 会找出有哪些模块和库是入口起点(直接和间接)依赖的。

默认值是 ./src/index.js,可以通过在 webpack configuration 中配置 entry 属性,来指定一个(或多个)不同的入口起点。例如:

webpack.config.js

module.exports = {
  entry: './path/to/my/entry/file.js'
}

输出(output)

output 属性告诉 webpack 在哪里输出它所创建的 bundle,以及如何命名这些文件。

主要输出文件的默认值是 ./dist/main.js,其他生成文件默认放置在 ./dist 文件夹中。可以通过在配置中指定一个 output 字段,来配置这些处理过程:

webpack.config.js

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.filename 和 output.path 属性,来告诉 webpack bundle 的名称,以及想要 bundle 生成(emit)到哪里。最上面导入的 path 模块是一个 Node.js 核心模块,用于操作文件路径。

loader

webpack 只能理解 JavaScript 和 JSON 文件。loader 让 webpack 能够去处理其他类型的文件,并将它们转换为有效 模块,以供应用程序使用,以及被添加到依赖图中。

注意,loader 能够 import 导入任何类型的模块(例如 .css 文件),这是 webpack特有的功能 其他打包程序或任务执行器的可能并不支持,官方团队认为这种语言扩展是很有必要的, 因为这可以使开发人员创建出更准确的依赖关系图。

webpack 的配置中 loader 有两个属性:

  • test 属性,用于标识出应该被对应的 loader 进行转换的某个或某些文件。
  • use 属性,表示进行转换时,应该使用哪个 loader。

webpack.config.js

const path = require('path');

module.exports = {
  output: {
    filename: 'my-first-webpack.bundle.js'
  },
  module: {
    rules: [
      { test: /\.txt$/, use: 'raw-loader' }
    ]
  }
};

在 webpack 配置中定义 rules 时,要定义在 module.rules 而不是 rules 中。如果没有按照正确方式去做,webpack 会给出警告。

请记住,使用正则表达式匹配文件时,不要为它添加引号。也就是说,/\.txt$/ 与 '/\.txt$/'/ "/\.txt$/" 不一样。前者指示 webpack 匹配任何以 .txt 结尾的文件,后者指示 webpack 匹配具有绝对路径 '.txt' 的单个文件; 这可能不符合预期的想法。

插件(plugin)

loader 用于转换某些类型的模块,而插件则可以用于执行范围更广的任务。包括:打包优化,资源管理,注入环境变量。

插件接口(plugin interface) 功能极其强大,可以用来处理各种各样的任务。

想要使用一个插件,只需要 require() 它,然后把它添加到 plugins 数组中。多数插件可以通过选项(option)自定义。也可以在一个配置文件中因为不同目的而多次使用同一个插件,这时需要通过使用 new 操作符来创建它的一个实例。

webpack.config.js

const HtmlWebpackPlugin = require('html-webpack-plugin'); // 通过 npm 安装
const webpack = require('webpack'); // 用于访问内置插件

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

在上面的示例中,html-webpack-plugin 为应用程序生成 HTML 一个文件,并自动注入所有生成的 bundle。

模式(mode)

通过选择 development, production 或 none 之中的一个,来设置 mode 参数,你可以启用 webpack 内置在相应环境下的优化。其默认值为 production。

module.exports = {
  mode: 'production'
};

构建项目

1、新建

新建一个空文件夹,用于创建项目,使用 npm init 命令创建一个 package.json 文件。

输入这个命令后,终端会问你一系列诸如项目名称,项目描述,作者等信息,也可以使用 npm init -y

这个命令来一次生成 package.json 文件。

如下图:

2、安装 webpack

安装 webapck 时需要把 webpack-cli 也装上是因为在 webpack4.x 版本后 webpack 模块把一些功能分到了 webpack-cli 模块,所以两者都需要安装,安装方法如下:

npm install webpack webpack-cli --global    //这是安装全局webpack及webpack-cli模块

3、新建文件目录

在根目录件夹中新建两个文件夹,分别为 src 文件夹和 dist 文件夹,接下来再创建三个文件:此时,项目结构如下

  • index.html --放在 dist 文件夹中;
  • hello.js --放在 src 文件夹中;
  • index.js --放在 src 文件夹中;

a、index.html 中写下 html 代码,它的作用是为引入打包后的 js 文件:

<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Webpack Project</title>
  </head>
  <body>
    <div id="root"></div>
    <script src="bundle.js"></script>
    <!--这是打包之后的js文件,我们暂时命名为bundle.js-->
  </body>
</html>

b、在 hello.js 中导出模块:

// hello.js
module.exports = function() {
  let hello = document.createElement('div')
  hello.innerHTML = 'Hello world!'
  return hello
}

c、在 index.js 中引入这个模块(hello.js):

//index.js
const hello = require('./hello.js')
document.querySelector('#root').appendChild(hello())

打开 index.html 就可以看到我们的页面了

4、配置 webpack.config.js

可以在当前项目的根目录下新建一个配置文件 webpack.config.js 用来配置打包方式。 webpack.config.js 配置如下

const path = require('path') // 处理绝对路径
module.exports = {
  entry: path.join(__dirname, '/src/index.js'), // 入口文件
  output: {
    path: path.join(__dirname, '/dist'), //打包后的文件存放的地方
    filename: 'bundle.js' //打包后输出文件的文件名
  }
}

有了这个配置文件,只需在终端中运行 webpack 命令就可进行打包,这条命令会自动引用 webpack.config.js 文件中的配置选项。

5、构建本地服务器

a、webpack-dev-server 配置本地服务器

Webpack 提供了一个可选的本地开发服务器,这个本地服务器基于 node.js 构建,它是一个单独的组件,在 webpack 中进行配置之前需要单独安装它作为项目依赖:

npm i webpack-dev-server -D

devServer 的一些配置选项:

  • contentBase :设置服务器所读取文件的目录,当前我们设置为"./dist"
  • port :设置端口号,如果省略,默认为 8080
  • inline :设置为 true,当源文件改变时会自动刷新页面
  • historyApiFallback :设置为 true,所有的跳转将指向 index.html
// webpack.config.js
const path = require('path')
module.exports = {
  entry: path.join(__dirname, '/src/index.js'), // 入口文件
  output: {
    path: path.join(__dirname, '/dist'), //打包后的文件存放的地方
    filename: 'bundle.js' //打包后输出文件的文件名
  },
  devServer: {
    contentBase: './dist', // 本地服务器所加载文件的目录
    port: '8088', // 设置端口号为8088
    inline: true, // 文件修改后实时刷新
    historyApiFallback: true 
  }
}

b、package.json 文件中添加启动和打包命令

  "scripts": {
    "build": "webpack",
    "dev": "webpack-dev-server --open"
  },

这样就可以用以下命令进行本地运行或者打包文件:

  • npm run dev 启动本地服务器,webpack-dev-server 就是启动服务器的命令,--open 是用于启动完服务器后自动打开浏览器。
  • npm run build 执行打包命令

此时,只要输入 npm run dev 就可以在http://localhost:8088/ 中查看页面。

6、配置常用 loader

loader 可以让 webpack 能够去处理那些非 JavaScript 文件(webpack 自身只理解 JavaScript)。loader 可以将所有类型的文件转换为 webpack 能够处理的有效模块,然后你就可以利用 webpack 的打包能力,对它们进行处理。

a、配置 css-loader 和 sass-loader

要加载一个 css 文件,需要安装配置 style-loader 和 css-loader。

  • css-loader:加载.css 文件
  • style-loader:使用 style 标签将 css-loader 内部样式注入到我们的 HTML 页面
const path = require('path')
module.exports = {
  entry: path.join(__dirname, '/src/index.js'), // 入口文件
  output: {
    path: path.join(__dirname, '/dist'), //打包后的文件存放的地方
    filename: 'bundle.js' //打包后输出文件的文件名
  },
  devServer: {
    contentBase: './dist', // 本地服务器所加载文件的目录
    port: '8088', // 设置端口号为8088
    inline: true, // 文件修改后实时刷新
    historyApiFallback: true //不跳转
  },
  module: {
    rules: [
      {
        test: /\.css$/, // 正则匹配以.css结尾的文件
        use: ['style-loader', 'css-loader']
      {
        test: /\.(scss|sass)$/, // 正则匹配以.scss和.sass结尾的文件
        use: ['style-loader', 'css-loader', 'sass-loader']
      }
    ]
  }
}

b、配置 Babel-loader

Babel 其实是一个编译 JavaScript 的平台,它可以编译代码达到以下目的:

  • 能使用最新的 JavaScript 代码(ES6,ES7...)
  • 能使用基于 JavaScript 进行了拓展的语言,比如 React 的 JSX;
module: {
  ...
  rules: [
    {
      test: /\.js$/,
      loader: 'babel-loader',
      include: [resolve('src')]
    }
  ]
}

c、理图片

处理图片资源时,我们常用的两种 loader 是 file-loader 或者 url-loader。 当使用 url-loader 加载图片,图片小于上限值,则将图片转 base64 字符串,否则使用 file-loader 加载图片。

module: {
  ...
  rules: [
    {
      test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
      loader: 'url-loader',
      options: {
        limit: 10000,
        name: utils.assetsPath('img/[name].[hash:7].[ext]')
      }
    }
  ]
}

7、配置常用插件

a、自动生成 html 文件(HtmlWebpackPlugin)

1、安装插件:

npm i html-webpack-plugin -D

2、把 dist 文件夹清空

3、在根目录新建 index.html,内容和原来的 html 一致,只是不引入 js 文件。

4、webpack.config.js 中引入 HtmlWebpackPlugin 插件

plugins: [
  new HtmlWebpackPlugin({
    filename: 'index.html',
    template: 'index.html',
    inject: true,
    minify: {
      removeComments: true,
      collapseWhitespace: true,
      removeAttributeQuotes: true
    }
  })
]

b、增加 css 前缀

写 css 时,一些属性需要手动加上前缀,在 webpack 中可以自动加上:

1、安装

npm i postcss-loader autoprefixer -D

2、在项目根目录下新建 postcss.config.js 文件

在项目根目录下新建 postcss.config.js 文件

module.exports = {
  plugins: [
    require('autoprefixer') // 引用autoprefixer模块
  ]
}
module.exports = {
   ...
  module: {
    rules: [
      {
        test: /\.css$/, // 正则匹配以.css结尾的文件
        use: [
          { loader: 'style-loader' }, // 这里采用的是对象配置loader的写法
          { loader: 'css-loader' },
          { loader: 'postcss-loader' } // 使用postcss-loader
        ]
      }
       ...
    ]
  }
   ...
}

c、css分离

将CSS提取为独立的文件的插件,对每个包含css的js文件都会创建一个CSS文件,支持按需加载css和sourceMap

安装

npm install --save-dev mini-css-extract-plugin

使用:

const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      // 类似 webpackOptions.output里面的配置 可以忽略
      filename: '[name].css',
      chunkFilename: '[id].css',
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              // 这里可以指定一个 publicPath
              // 默认使用 webpackOptions.output中的publicPath
              publicPath: '../'
            },
          },
          'css-loader',
        ],
      }
    ]
  }
}

参考文章

1、www.webpackjs.com/concepts/ 【官方文档】

2、 juejin.cn/post/684490… 【掘金】