webpack4.x学习笔记

栏目: JavaScript · 发布时间: 5年前

内容简介:webpack是一个模块打包工具,将每个资源文件看做是一个个模块,webpack依据打包规则将所有资源处理后打包到指定文件打包方案,告诉webpack如何处理特定的文件一段能扩展webpack功能的代码,可以在webpack运行到某个时刻的时候,帮助webpack做一些事情

webpack是一个模块打包工具,将每个资源文件看做是一个个模块,webpack依据打包规则将所有资源处理后打包到指定文件

支持的模块引入规范

  • CommonJS
// 导入
import 模块名 from 模块路径;
// 导出
export default 模块名;
export const 模块名 = 模块内容;
复制代码
  • CMD
// 导入
var 模块名 = required(模块路径);
// 导出
module.exports = 模块名;
复制代码
  • AMD

Mac webpack环境搭建

  1. 安装nodejs,webpack依赖node.js
    • 进入node官网,点击带有 LTS 字眼按钮,下载稳定版node
    • 点击压缩的安装包,一直点击下一步即可,
    • 最后执行 node -vnpm -v 查看版本号,如果有说明安装成功,否则卸载,重新执行上诉步骤
  2. 执行 npm init ,初始化项目,一直按回车键,在新建的文件夹会生成一个package.json文件
{
  "name": "webpack-demo",
  "version": "1.0.0",
  "private": true, // 是一个私有项目,不会上传到npm线上
  "description": "",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}
复制代码
  1. 安装webpack(我的是4.34.0)
    • 全局安装(不推荐)
      npm install webpack webpack-cli -g
      webpack -v 查看全局webpack版本号
      
    • 局部安装(推荐)
      npm install webpack webpack-cli
      npx webpack -v 查看版本号 npx查找的是当前目录下的webpack
      
    • 卸载
      • npm uninstall webpack webpack-cli
    • 查看webpack版本记录
      • npm info webpack

webpack配置文件(webpack.config.js)

const path = require('path'); // 导入node的path模块

module.exports = {
  entry: './src/index.js', // 打包入口文件
  output: {
    filename: 'bundle.js', // 打包出的文件名
    path: path.resolve(__dirname, 'dist') // 存放打包出的文件路径(绝对路径)
  }
};
复制代码

webpack打包命令

// global
webpack 文件名

// local
npx webpack 文件名
复制代码

配置npm script(简化打包命令书写)

// package.json文件
  "scripts": {
    "bundle": "webpack" 
    // 执行npm run bundle命令,
    // webpack会执行package.json文件下script字段里bundle对应的映射命令
  }
复制代码

webpack-cli作用

  • 能够在终端使用webpack命令

webpack打包日志

Hash: 178b79cd0f5fd66a90e5
Version: webpack 4.34.0     -- webpack版本
Time: 380ms     -- 打包耗时
Built at: 06/18/2019 7:59:32 PM
// 文件名     大小   每一个打包的js文件id   每一个打包的js文件名
    Asset      Size  Chunks             Chunk Names
bundle.js  1.17 KiB       0  [emitted]  main
Entrypoint main = bundle.js // 入口文件名(mian)
[0] ./src/index.js 203 bytes {0} [built] // 文件索引 文件路径 文件体积
[1] ./src/Footer.js 79 bytes {0} [built]
[2] ./src/Header.js 79 bytes {0} [built]
[3] ./src/Slider.js 79 bytes {0} [built]
复制代码

mode项

  • 设置webpack的打包环境
  • development:开发环境,专注于打包速度,不会压缩和tree sharking代码
  • production:生成环境,专注于打包后的文件体积,会进行文件压缩和tree sharking去除无用代码,减小文件体积

Loader是什么

打包方案,告诉webpack如何处理特定的文件

module项配置loader

// package.json
  module: { // 打包的模块
    // 打包规则
    rules: [{
      test: /\.jpg$/, // 正则匹配使用loader解析的模块后缀名
      use: {
        loader: 'file-loader' // 用于解析该模块的loader
      }
    }]
  }
复制代码

webpack打包流程

  1. 允许npm run bundle(实际上是执行webpack打包命令)
  2. webpack查看webpack配置文件,根据配置进行打包
  3. 如果遇到js文件,webpack自己处理解析;如果遇到其他文件,webpack会将该文件交给module项里能处理该类文件的loader处理,处理完后,将文件地址返回给引用该文件的变量

使用Loader打包静态资源(图片篇)

  • file-loader
    • 作用:将js中引用的文件资源抽离成单独的文件
{
      test: /\.(jpg|png|gif)$/,
      use: {
        loader: 'file-loader',
        options: {
         // 占位符 placeholder
          name: '[name]_[hash].[ext]',
          outputPath: 'images/' // 处理后的文件存放位置: dist/images/xxx.png
        }
      }
    }
复制代码
  • url-loader
    • 作用:将js中引用的文件资源转换为base64格式
{
      test: /\.(jpg|png|gif)$/,
      use: {
        loader: 'url-loader',
        options: {
          name: '[name]_[hash].[ext]',
          outputPath: 'images/', // 处理后的文件存放位置: dist/images/xxx.png,
          // size > 2.048kb 效果与file-loader一致
          // size < 2.048kb 转换为base64字符串放入bundle.js中
          limit: 2048
        }
      }
    }
复制代码

使用Loader打包静态资源(样式篇)

  • less-loader
    • 作用:将less文件转换为css文件
{
        test: /\.(c|le)ss/,
        use: ['less-loader']
}
复制代码
  • postcss-loader
    • 作用:生成css AST树,方便postcss周边插件处理css代码
// webpack配置
{ // 样式处理
        test: /\.(c|le)ss/,
        use: ['postcss-loader', 'less-loader']
    }
复制代码
// postcss.config.js配置
module.exports = {
  plugins: [
    require('autoprefixer'), // 自动添加属性前缀(后编译器)
  ]
};
复制代码
  • css-loader
    • 作用:分析多个css文件间的引用关系,将多个css文件合并成一段css
{
        test: /\.(c|le)ss/,
        use: ['css-loader', 'postcss-loader', 'less-loader']
}
复制代码
  • style-loader
    • 作用:将css-loader处理过后的内容,生成style标签插入到head标签里
{       // loader执行顺序为从上到下,从右到左
        test: /\.(c|le)ss/,
        use: ['style-loader', 'css-loader', 'postcss-loader', 'less-loader']
}
复制代码

使用Loader打包静态资源(字体篇)

{ // 字体处理
        test: /\.(eot|svg|ttf|woff|woff2)$/,
        use: [
          {
            loader: 'file-loader',
            options: {
              name: '[name]_[hash].[ext]',
              outputPath: 'assets/font/',
            }
          }
        ]
      }
复制代码

什么是Plugins?

一段能扩展webpack功能的代码,可以在webpack运行到某个时刻的时候,帮助webpack做一些事情

  • html-webpack-plugin
    • 作用:根据html模板文件,生成一个新的html,并将打包生成的js引入html文件中
// 导入
const HtmlWebpackPlugin = require('html-webpack-plugin');

  plugins: [
    new HtmlWebpackPlugin({ // 根据模板html, 生成新html文件
      template: 'src/index.html', // html模板
    })
  ]
复制代码
  • clean-webpack-plugin
    • 作用:删除文件指定文件夹
// 导入(新版本写法)
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

plugins: [
    new CleanWebpackPlugin(), // 删除当前目录dist文件夹
  ]
复制代码

SourceMap配置

打包代码与源码之间的一种映射关系,能够让开发人员快速的定位错误发生的位置

  • source-map:会生成一个.map文件
module.exports = {
  devtool: 'source-map',
};
复制代码
webpack4.x学习笔记
  • inline-source-map:将map映射以base64格式写入main.js
module.exports = {
  devtool: 'inline-source-map',
};
复制代码
webpack4.x学习笔记
  • cheap-source-map:只显示出错的行数
module.exports = {
  devtool: 'cheap-source-map',
};
复制代码
webpack4.x学习笔记
  • eval:使用eval形式执行代码
module.exports = {
  devtool: 'eval',
};
复制代码
webpack4.x学习笔记
// development:cheap-module-eval-source-map(推荐)
// production:cheap-module-source-map(推荐)
复制代码

点击查看devtool配置项

WebpackDevServer配置

  • 安装webpack-dev-server
npm install webpack-dev-server --save-dev
复制代码
  • 配置执行命令
"scripts": {
    "start": "webpack-dev-server"
 }
复制代码
  • 配置webpack
devServer: { // 设置开发服务
    contentBase: './dist', // 根目录
    open: true, // 自动打开浏览器
    port: 8080, // 端口号
    proxy: { // 设置接口代理(解决跨域)
      '/api': 'https://localhost:3000'
    }
 }
复制代码

node环境使用WebpackDevServer功能

  • 安装express(node的框架)
npm install express --save-dev
复制代码
  • 安装webpack-middleware(监听src目录下文件变化)
npm install webpack-middleware --save-dev
复制代码
  • 编写server.js
const express = require('express');
const webpack = require('webpack');
const WebpackMiddleWare = require('webpack-middleware');
const config = require('./webpack.config');

// 生成express实例(服务器)
const app = express();
// 创建webpack编译器(能够进行webpack打包)
const complier = webpack(config);

// 使用webpack-middleware插件监听webpack打包的文件变化
app.use(WebpackMiddleWare(complier, {}));

// 开启监听
app.listen(3000, () => {
  console.log('server is running at 3000');
});
复制代码
  • 配置server执行命令
"scripts": {
    "server": "node server.js"
 }
复制代码

热模块替换(Hot Module Replacement)

实现局部更新,而非浏览器页面刷新

devServer: {
    hot: true, // 开启HMR
    hotOnly: true, // 不更新浏览器
 },
 plugins: [
    new webpack.HotModuleReplacementPlugin()
 ]
  
  // entery文件末尾添加
 if (module.hot) {
  module.hot.accept();
}
复制代码

配置Babel编译ES6语法

babel:只能解析ES的语法,而不能解析对象的API,Promise等; @babel/polyfill:解析babel不能解析的部分

  • 安装babel-loader、@babel/preset-env、@babel/core、@babel/polyfill
npm install babel-loader @babel/preset-env @babel/core @babel/polyfill
复制代码
  • 配置
module: {
    rules: [
     { // babel处理
        test: /.js$/,
        exclude: /node_modules/, // 排除文件
        loader: 'babel-loader'
      }
    ]
  }
复制代码
// .babelrc文件
{
  "presets": [
    [
      "@babel/preset-env", // 将ES5以上的语法转换为ES5版本
      {
        "useBuiltIns": "usage" // 按需使用polyfill
      }
    ]
  ]
}
复制代码
// index.js
import '@babel/polyfill';
复制代码

使用babel-polyfill可能会造成全局变量名污染,如果有使用babel打包第三方包,则使用transform-runtime方案

配置React代码打包环境

  • 安装react、react-dom
npm install react react-dom --save
复制代码
  • 安装@babel/preset-react
npm install @babel/preset-react --save-dev
复制代码
  • .babelrc配置
{
  "presets": [
    ["@babel/preset-react"]
  ]
}
复制代码

Tree Sharking

删除模块中未使用的内容,减小打包体积(只支持ES Module的引入方式)

开发环境

  • 配置webpack.config
module.exports = {
    mode: 'development'
    optimization: {
        usedExports: true, // 打包被引用的模块
    }
};
复制代码
  • 配置package.json
{
    "sideEffects": false // 所有模块都进行tree sharking
}
复制代码

生成环境

  • 配置webpack.config
module.exports = {
    mode: 'production'
};
复制代码
  • 配置package.json
{
    "sideEffects": false // 所有模块都进行tree sharking
}
复制代码

Development和Production模式

  • development(开发模式)
    • 关注打包速度,不会进行代码压缩
  • production(生产模式)
    • 关注打包文件体积,会对代码进行压缩,tree sharking等操作

根据模式拆分webpack.config文件

  • 安装webpack-merge用以合并webpack配置文件
npm install webpack-merge --save-dev
复制代码
  • webpack.common.js:公共配置
const path = require('path'); // 导入node的path模块
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

module.exports = {
  entry: {
    main: './src/index.js', // 打包入口文件
  },
  output: {
    filename: 'script/[name].js', // 打包出的文件名
    path: path.join(__dirname, '../', 'dist'), // 存放打包出的文件路径(绝对路径)
    // publicPath: './', // 公共路径
  },
  module: { // 打包模块
    // 打包规则
    rules: [
      { // babel处理
        test: /.js$/,
        exclude: /node_modules/, // 排除文件
        loader: 'babel-loader'
      },
      { // 图片处理
        test: /\.(jpg|png|gif)$/,
        use: {
          loader: 'url-loader',
          options: {
            name: '[name]_[hash].[ext]',
            outputPath: 'images/', // 处理后的文件存放位置: dist/images/xxx.png
            limit: 10240, // 当处理的文件大小大于2048kb,效果与file-loader一致;小于时,转换为base64字符串放入bundle.js中
          }
        }
      }, { // 字体处理
        test: /\.(eot|svg|ttf|woff|woff2)$/,
        use: [
          {
            loader: 'file-loader',
            options: {
              name: '[name]_[hash].[ext]',
              outputPath: 'font/',
            }
          }
        ]
      }, { // csv文件处理
        test: /\.(csv|tsv)$/,
        use: ['csv-loader']
      }, { // xml文件处理
        test: /\.xml$/,
        use: ['xml-loader']
      }, { // 样式处理
        test: /\.less/,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              importLoaders: 2, // 让less文件里引入的其他文件也经过后面两个loader处理
              // modules: true, // css模块化(css文件只在当前模块有效)
            }
          },
          'postcss-loader',
          'less-loader'
        ]
      }, {
        test: /\.css$/,
        use: ['style-loader', 'css-loader', 'postcss-loader']
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({ // 根据模板html, 生成新html文件
      template: 'src/index.html'
    }),
    new CleanWebpackPlugin({ // 清除文件夹
      dry: false
    })
  ]
};
复制代码
  • webpack.prod.js:生产环境配置
const webpackMerge = require('webpack-merge'); // 合并webpack配置文件
const commonConfig = require('./webpack.comm');

const prodConfig = {
  mode: 'production', // 打包环境
  // development:cheap-module-eval-source-map(推荐)
  // production:cheap-module-source-map(推荐)
  devtool: 'none', // 设置源文件与打包文件的映射关系
};

module.exports = webpackMerge(commonConfig, prodConfig);
复制代码
  • webpack.dev.js:开发模式配置
const webpack = require('webpack');
const webpackMerge = require('webpack-merge'); // 合并webpack配置文件
const commonConfig = require('./webpack.comm');

const devConfig = {
  mode: 'development', // 打包环境
  // development:cheap-module-eval-source-map(推荐)
  // production:cheap-module-source-map(推荐)
  devtool: 'cheap-module-eval-source-map', // 设置源文件与打包文件的映射关系
  devServer: { // 设置开发服务
    contentBase: './dist', // 根目录
    open: true, // 自动打开浏览器
    port: 8080, // 端口号
    hot: true, // 开启HMR
    hotOnly: true, // 不更新浏览器
    proxy: { // 设置接口代理(解决跨域)
      '/api': 'https://localhost:3000'
    }
  },
  optimization: {
    usedExports: true, // 打包被引用的模块
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin()
  ]
};

module.exports = webpackMerge(commonConfig, devConfig);
复制代码
  • package.json修改
"scripts": {
    "start": "webpack-dev-server --config ./build/webpack.dev.js",
    "build": "webpack --config ./build/webpack.prod.js",
    "server": "node server.js"
  },
复制代码

Code Splitting进行代码分割

将重复代码抽离出来形成单独的chunk,避免单个文件过大,而造成文件请求时间过长

同步代码实现代码分割,配置optimization项

optimization: {
    splitChunks: { // 代码分割
      chunks: 'all', // 自动检测应该分离的代码
    }
  }
复制代码

异步代码实现代码分割(import导入的模块)

webpack会自动将异步代码打包到单独的文件中,但webpack在打包时,无法识别动态异步引入语法,所以我们需要安装@babel/plugin-syntax-dynamic-import来支持动态异步引入语法

  • 安装@babel/plugin-syntax-dynamic-import
# 支持动态异步引入模块
npm install --save-dev @babel/plugin-syntax-dynamic-import --save-dev
复制代码
  • 配置.babelrc文件
{
  "plugins": [
    "@babel/plugin-syntax-dynamic-import"
  ]
}
复制代码

SplitChunksPugin配置参数

  • webpack默认配置项
splitChunks: {
    chunks: "async",
    minSize: 30000,
    minChunks: 1,
    maxAsyncRequests: 5,
    maxInitialRequests: 3,
    automaticNameDelimiter: '~',
    name: true,
    cacheGroups: {
        vendors: {
            test: /[\\/]node_modules[\\/]/,
            priority: -10
        },
    default: {
            minChunks: 2,
            priority: -20,
            reuseExistingChunk: true
        }
    }
}
复制代码
  • 注释版
splitChunks: {
      chunks: 'all', // 代码分割目标:async(异步代码) all(异步和同步代码) initial(同步代码)
      minSize: 30000, // 模块size > minSize(30KB)进行代码分割
      // maxSize: 50000, // 分割出的模块size > maxSize(50KB)进行二次分割
      minChunks: 1, // 模块使用次数 > minChunks进行代码分割
      maxAsyncRequests: 5, // 异步模块内部最大并行请求数
      maxInitialRequests: 3, // 入口并行加载的最大请求数(入口文件最多能拆分3个文件被http请求)
      automaticNameDelimiter: '~', // 文件名连接符
      name: true, // 自动生成文件名
      cacheGroups: { // 分割代码缓存组(同步代码分割有效)
        vendors: { // vendors组,入口文件:main.js
          test: /[\\/]node_modules[\\/]/, // 分割nodule_modules下的代码
          priority: -10, // 分割优先级(当模块符合多个组时,放在优先级高的组中)
          filename: 'vendors.js' // 打包文件名
        },
        default: { // default组,入口文件:main.js
          priority: -20,
          reuseExistingChunk: true, // 忽略已打包过的模块
          filename: 'common.js'
        }
      }
    }
复制代码

打包分析

info

  • 安装 webpack-bundle-analyzer插件
npm install --save-dev webpack-bundle-analyzer
复制代码
  • webpack中使用
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
    plugins: [
        new BundleAnalyzerPlugin()
    ]
};
复制代码

Preloading

与核心js文件一起下载(不推荐)

Prefetching(加快首屏渲染)

等待核心js文件下载完毕,网络带宽空闲了,再去下载其他模块资源(推荐)

提取css

  • 安装mini-css-extract-plugin
# 将css从js文件中抽离出来
npm install --save-dev mini-css-extract-plugin
复制代码
  • 配置webpack.prod.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
     module: {
        rules: [{ // 样式处理
        test: /\.(le|c)ss/,
        use: [
            {
            loader: MiniCssExtractPlugin.loader,
            options: {
                publicPath: '../', // 提取出来的css文件里都会添加公共路径
                hmr: process.env.NODE_ENV === 'development'
            }
        }, {
            loader: 'css-loader',
            options: {
                importLoaders: 2, // 让less文件里引入的其他文件也经过后面两个loader处理
                // modules: true, // css模块化(css文件只在当前模块有效)
            }
            },
            'postcss-loader',
            'less-loader'
        ]
    }]
  },
    plugins: [
        new MiniCssExtractPlugin({ // 抽离js文件里的css
            filename: 'static/css/[name].[hash].css', // html直接引入的css文件
            chunkFilename: 'static/css/[id].[hash].css' // 间接引入的css文件
        })
  ],
};
复制代码
  • 安装optimize-css-assets-webpack-plugin
# 进行css压缩
npm install --save-dev optimize-css-assets-webpack-plugin
复制代码
  • 配置webpack.prod.js
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');

module.exports = {
    optimization: {
        minimizer: [
            new OptimizeCSSAssetsPlugin({ // css代码压缩
            })
        ]
    }
};
复制代码

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

你的品牌,价值千万

你的品牌,价值千万

温迪 / 人民邮电出版社 / 2018-7-1 / 49.00元

“大道无术,万法归心。” 不管是互联网、社交媒体,还是 AI 怎样让人眼花缭乱。从“真心”出发塑造的个人品牌,都将带你从容面对任何一种变化的冲击。现代生活变得越来越透明,如果你不懂得如何真实、精准地定位和呈现自己,你的个人品牌在 碎片信息中被误解、被曲解就是一种必然。 本书分四步引导你剖析自己、发现自我,构建可持续的品牌生态系统,策划品牌战略,提升个人呈现力,并在最后带你勾画出一幅完整的个人......一起来看看 《你的品牌,价值千万》 这本书的介绍吧!

URL 编码/解码
URL 编码/解码

URL 编码/解码

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具