Webpack | 青训营

58 阅读6分钟

一、Webpack简介

1、webpack是什么?

Webpack是一种前端资源构建工具,一个静态模块打包器(module bundler)

在 Webpack看来,前端的所有资源文件(js/json/css/img/less/...)都会作为模块处理

它将根据模块的依赖关系进行静态分析,打包生成对应的静态资源(bundle)

2、Webpack的五个核心概念

  1. Entry

入口指示 Webpack以哪个文件为入口七点开始打包,分析构建内部依赖图

  1. Output

输出指示 Webpack打包后的资源bundles输出到哪里去,以及如何命名

  1. Loader

Loader让Webpack 能够去处理那些非JavaScript文件(webpack自身只理解JavaScrpit)

  1. Plugins

插件可以用于执行范围更广的任务.插件的范围包括,从打包优化和压缩,一直到重新定义环境中的变量等

  1. Mode

模式指示Webpack使用相应模式的配置

选项描述特点
development会将process.env.NODE_ENV的值设置为development. 启用NamedChunksPlugin和NamedModulesPlugin能让代码本地调试运行的环境
production启动好多东西....能让代码优化上线运行的环境

3、Webpack初体验

Ⅰ、安装与使用

  1. 先安装全局webpack包(也可以不安装)
 npm i webpack webpack-cli -g 
  1. 初始化项目npm包
 npm init
  1. 安装当前项目webpack包
 npm i webpack webpack-cli -D

Ⅱ、编译打包应用

  1. 创建相关文件夹与文件(build与src文件加与index.js)
  2. 运行指令

a)开发环境指令:webpack ./src/index.js -o ./build/built.js --mode=development

webpack就会以./src/index.js为入口文件开始打包,打包后输出到./build/built.js整体打包环境,是开发环境

b)生产环境指令:webpack ./src/index.js -o ./build/built.js --mode=production

做的都是一样的,环境是生产环境

c)当配置文件写好后,可以直接使用webpack指令进行打包



二、Webpack配置详解

1、在学习过程中这部分本是最后学习的,但本人认为可先放前面,先了解后再去使用.

建议:--> --> --> 顺序翻阅,先粗略过一遍,有不懂的留着疑惑看二、三,最后再回头看这里

2、webpack配置实际是创建一个对象,所以里面的属性并没有执行顺序,即使你将entry写在output下面都可以执行,因为到时候执行的时候是webpack通过调用对象属性进行实现顺序的

Ⅰ- entry

entry:入口起点,有三种形式写法

1、string --> './src/index.js'

单入口:打包形成一个chunk(模块),输出一个bundle(包)文件

此时默认的chunk名称是main

2、array --> ['./src/index.js','./src/add.js']

多入口:所有入口文件最终只会形成一个chunk,输出出去只有一个bundle文件(类似将add.js打包进index.js中)

-->通常只有在HMR功能中使用, 让html热更新生效使用

3、object --> {index:'./src/index.js',add:'./src/add.js'}

多入口:有几个入口文件就形成几个chunk,输出几个bundle文件

此时chunk名称是 key

4、特殊用法(混合使用)

通常在dll优化功能中使用

 module.exports = {
   entry: {
       // 所有入口文件最终只会形成一个chunk, 输出出去只有一个bundle文件。
     index: ['./src/index.js', './src/count.js'], 
        // 形成一个chunk,输出一个bundle文件。
     add: './src/add.js'
   },
   output: {
     filename: '[name].js',
     path: resolve(__dirname, 'build')
   },
   plugins: [new HtmlWebpackPlugin()],
   mode: 'development'
 };
 ​

Ⅱ- output

使用entry为单入口为例讲解

1、filename:文件名称(指定名称+目录)

2、chunkFilename:非入口chunk的名称,如未指定这项,在入口文件中导入的js打包也会用上filename的文件名称进行命名,但是名字与入口文件冲突,就会使用0~∞数字命名,不容易区分

3、path:输出文件目录(将来所有资源输出的公共目录)

4、publicPath:所有资源引入公共路径的前缀 -- 'img/a.jpg'-->'/img/a.jpg' 这个适合生产环境使用

这两者变化区别:前者是将imgs目录跟在当前目录路径后面,后者是将imgs跟在服务器地址后面

5、library:'[name]' //整个库向外暴露的变量名 实际上使用var声明

6、libraryTarget:将变量名添加到哪个对象上

a) libraryTarget: 'window' 适合浏览器端

b) libraryTarget: 'global' 适合node

c) libraryTarget: 'commonjs' 使用commonjs方式进行模块导出

 const { resolve } = require('path');
 const HtmlWebpackPlugin = require('html-webpack-plugin');
 ​
 module.exports = {
   entry: './src/index.js',
   output: {
     // 文件名称(指定名称+目录)
     filename: 'js/[name].js',
     // 输出文件目录(将来所有资源输出的公共目录)
     path: resolve(__dirname, 'build'),
     // 所有资源引入公共路径前缀 --> 'imgs/a.jpg' --> '/imgs/a.jpg' 适合生产环境使用, 
      // 这两者地址区别:前者是将imgs目录跟在当前目录后面 ,后者是将imgs跟在服务器地址后面
     publicPath: '/',
     chunkFilename: 'js/[name]_chunk.js', // 非入口chunk的名称
     // library: '[name]', // 整个库向外暴露的变量名  定义为var
     // libraryTarget: 'window' // 变量名添加到哪个上 browser(适用浏览器端)
     // libraryTarget: 'global' // 变量名添加到哪个上 node(适用node服务端)
     // libraryTarget: 'commonjs' //使用commonjs的方式模块导出
   },
   plugins: [new HtmlWebpackPlugin()],
   mode: 'development'
 };
 ​

Ⅲ- module

1、test:文件名匹配规则,后面参数是一个正则

2、exclude:排除匹配某个目录下的内容 --> exclude: /node_modules/ ->排除node_modules下的文件

3、include:只检查 某个目录下的文件 --> include: resolve(__dirname, 'src') ->只检查 src 下的js文件

4、loaderuse:单个loader使用loader,多个loader用use

5、enforce:指定该配置的执行顺序: enforce:'pre'(优先执行) > 默认 > enforce:'post'(延后执行)

6、options:指定这个loader的配置选项

7、oneOf: []:里面的配置只会生效一次,即里面有100个配置,当我一个文件进入这里检测,可能第10个配置匹配到了就生效,然后该文件就不会进行下面90次匹配,如果是不放oneOf里面的配置,就会完全执行100次匹配,性能优化使用

该部分知识在优化部分:当你使用enlint与babel两种配置进行对于js文件的匹配的情景下会使用

 const { resolve } = require('path');
 const HtmlWebpackPlugin = require('html-webpack-plugin');
 ​
 module.exports = {
   entry: './src/index.js',
   output: {
     filename: 'js/[name].js',
     path: resolve(__dirname, 'build')
   },
   module: {
     rules: [
       {
         test: /.js$/,
         // 排除node_modules下的js文件
         exclude: /node_modules/,
         // 只检查 src 下的js文件
         include: resolve(__dirname, 'src'),
         // 单个loader用loader
         loader: 'eslint-loader',
         // 多个loader用use
         //use: ['style-loader', 'css-loader']
         // 优先执行
         enforce: 'pre',
         // 延后执行
         // enforce: 'post',
         //指定这个loader的配置选项
         options: {}
       },
       {
         // 以下配置只会生效一个
         oneOf: []
       }
     ]
   },
   plugins: [new HtmlWebpackPlugin()],
   mode: 'development'
 };

Ⅳ- resolve

该resolve并不是path的relove,而是配置中的resolve配置项:解析模块的规则

1、alias:配置解析模块路径别名: 优点简写路径 缺点路径没有提示

2、extensions:配置省略文件路径的后缀名

3、modules:告诉webpack解析模块是去哪个目录 -->如果不指定会webpack会一层一层往外找,造成不必要的性能浪费