0


webpack打包教程

一、Webpack 是什么

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

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

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

二、为什么要使用webpack?

当我们在文件里使用less,sass等预处理语言,或者使用es6等新最新语法,很多浏览器不能识别不能解析,所以需要一些工具去把这些文件进行编译浏览器能识别的语法,过去需要一个一个的工具,很麻烦,所以后来出现了webpack把一系列的工具整合成为一个工具

三、webpack是怎么打包的?

从项目的入口文件开始,再根据入口文件的依赖关系对引入的资源(less/es6.. 称之为模块)依次进行打包形成chunk文件代码块,通过这个代码块依次对引入的资源进行分类编译,这个编译的过程叫做打包,打包之后输出的文件为bundle

四、webpack的五个核心概念

4.1、Entry
入口(Entry)指示 Webpack 以哪个文件为入口起点开始打包,分析构建内部依赖图

    4.2、Output
             输出(Output)指示 Webpack 打包后的资源 bundles 输出到哪里去,以及如何命名。

    4.3、Loader
             Loader 让 Webpack 能够去处理那些非 javaScript 文件(webpack 自身只能理解JavaScript)相当于翻译官的角色,将css,img等非js资源翻译能webpack能识别的资源

loader 和 plugins 的区别:

            loader:一般做一些比较傻瓜式的操作

            plugin:大部分都是插件来做,做一些比较复杂的事情

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

    4.5、Mode
             模式(Mode)指示 Webpack 使用响应模式的配置

五、webpack初体验

5.1、webpack的全局安装

// 基于nodejs平台运行的,模块化采用commonjs
npm i webpack webpack-cli -g
//同时下载webapck 和 webpack-cli 两个模块到全局
//也可以分开下载
npm i webpack -g
npm i webpack webpack-cli -g
//mac用户要加 sudo 字符启用管理员模式
 
// webpack 和 webpack-cli的关系 就如同 Vue 和 Vue-cli 的关系
// Vue 是一套框架, Vue-cli 是一套基于Vue.js的快速开发的完整系统
// webpack 是打包工具 webpack-cli就是提供了能够简化webpack的配置的工具

5.2、webpack的本地安装

npm init // 初始化文件夹生成package.json文件
npm i webpack webpack-cli -g

5.3、webpack指令

//运行指令:
//开发环境: 
webpack ./src/index.js -o ./build --mode=development
//把 ./src/index.js 文件打包输出到 ./build 文件夹下的main.js   --mode=development 模式为开发模式
//运行环境:
webpack ./src/index.js -o ./build --mode=production
//把 ./src/index.js 下的文件打包输出到 ./build 文件夹的main.js   --mode=development 模式为运行模式
 
//结论:
//1、webpack能处理js/json资源,不能处理css/img等其他资源
//2、生产环境和开发环境将ES6模块化编译成浏览器能识别的问题
//3、生产环境比开发环境多一个压缩js代码

5.4、处理css等非 js/json 资源方法 (新增 webpack.config.js 放在最外层)

/*
    webpack.config.js    webpack的配置文件
    作用:指示 webpack 干那些活(当你运行 webpack命令 时,会加载里面的配置)
    所有构件工具都是基于 nodejs 平台运行的! 模块化默认采用commonjs
*/
 
// resolve用来拼接绝对路径的方法
const {resolve} = require('path')
// webpack配置
module.exports={
    // 入口文件
    entry: './src/index.js',
    // 输出设置
    output: {
        //输出文件名称
        filename:'built.js',
        // 输出路径
        //__dirname  这是nodejs的变量,代表当前文件的目录绝对路径
        path:resolve(__dirname,'build')
    },
 
    // loader的配置
    module:{
        rules:[
            //详细loader配置
            //不同文件必须配置不同loader处理
            {
                // 匹配哪些文件
                test:/\.css$/,
                // 使用哪些loader,使用到的loader,需要npm下载之后才能打包成功
                use:[
                    //use数组中loader执行顺序:从右到左,从下到上 依次执行
                    // 创建style标签,将js中的样式资源插入进行,添加到head中生效
                    'style-loader',
                    // 将css文件变成commonjs模块加载到js中,里面内容是样式字符串
                    'css-loader'
                ]
            },
            {
                test:/\.less$/,
                use:[
                    'style-loader',
                    'css-loader',
                    // 将less文件编译成css文件
                    'less-loader'
                ]
            }
        ]
    },
 
    // 模式
    mode:'development'
}

六、webpack自动化打包

// 开发服务器 deserver:用来自动化(自动编译,自动打开浏览器,自动刷新浏览器)
// 只会在内存中编译打包,不会有任何输出, 关闭之后需要通过webpack打包一次才能达到最新编译内容 
// 所需依赖 webpack-dev-server 需要下载
// 启动devServe指令:webpack serve
devServer:{
    //代表我要运行的目录,一定是构建后的目录
    contentBase: resolve(__dirname,'build'),
    // 启动gzip压缩
    compress:true,
   // 设置端口号
    port:3000,
    // 自动打开浏览器
    open:true
 
}

七、webpack生产环境配置
7.1、生产环境和开发环境的区别
开发环境:
顾名思义就是可以让代码运行起来调试的的环境,在这个环境下,需要webpack去做一些编译,将资源编译成浏览器可以识别的资源,而且我们可以加入自动化的工具来让我们更加容易的调试
生产环境:
首先css文件经过打包生成的样式资源是整合在js中的,这样会使js体积变的很大,加载比较缓慢,而且需要加载完js之后才能去加载css样式,这时会产生闪屏现象,所以我们在生产环境打包时要将css样式抽离出来
代码要进行压缩处理
样式代码和js代码在浏览器端是有兼容性的,所以要做兼容处理
等等...
因为生产环境的要求比较高,而且编译时间会很久,所以这些操作需要在生产环境下做

    7.2、生产环境的配置
             7.2.1、将打包编译后的文件进行文件分类 loader中 outputPath 字段
// 输出设置 将js文件放入js文件夹内
    output: {
        //输出文件名称
        filename:'js/built.js',
        // 输出路径
        //__dirname  这是nodejs的变量,代表当前文件的目录绝对路径
        path:resolve(__dirname,'build'),
 
        // publicPath: './'
    },
    
    //outputPath 输出目录
    module:{
        rules:[
            // 打包其他资源都用file-loader
            // exclude 需要排除的资源
            {
                exclude:/\.(html|js|css)$/,
                loader:'file-loader',
                options:{
                    name:'[hash:10].[ext]'
                    outputPath:'other'
                }
            },
            {
                // 匹配图片资源
                test:/\.(jpg|png|gif)$/,
                loader: 'url-loader',
                options:{
                    limit: 8*1024,
                    esModule:false,
                    name:'[hash:10].[ext]',
                    outputPath:'imgs'
                }
            },
        ]
    }

7.2.2、抽离css资源

 
 
const { resolve } = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
 
module.exports={
  entry:'./src/index.js',
  output:{
      filename:'js/built.js',
      path:resolve(__dirname,'build')
  },
  module:{
      rules:[
          { 
              test:/\.css$/,
              use:[
                  // style-loader: 创建style样式,讲样式放进去
                  // 用这个loader取代 style-loader , 作用:提取js中的css为单独文件
                  MiniCssExtractPlugin.loader,
                  'css-loader'
              ]
          },
          {
              test:/\.less$/,
              use:[
                MiniCssExtractPlugin.loader,
                'css-loader',
                'less-loader'
              ]
          }
      ]
  },
  plugins:[
    new HtmlWebpackPlugin({
        template:'./src/index.html'
    }),
    // mini-css-extract-plugin 这个插件可以将css单独抽离出来需要先下载
    new MiniCssExtractPlugin({
        // 对文件进行重命名
        filename:'css/built.css'
    })
  ],
  mode:'development',

7.2.3、css兼容性

 
 
const { resolve } = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
 
// 设置环境变量
process.env.NODE_ENV = 'development'
 
module.exports={
  entry:'./src/index.js',
  output:{
      filename:'js/built.js',
      path:resolve(__dirname,'build')
  },
  module:{
      rules:[
          { 
              test:/\.css$/,
              use:[
                  // style-loader: 创建style样式,讲样式放进去
                  // 用这个loader取代 style-loader , 作用:提取js中的css为单独文件
                  MiniCssExtractPlugin.loader,
                  'css-loader',
                  // css兼容性处理:postcss方法:需要先下载 postcss-loader postcss-preset-env
                  // 要放在css-loader之下 less-loader之上的位置
                  // 帮 postcss 找到 package.json 中 browserslist 里面的配置,通过配置加载指定的css兼容性样式
                  // 默认生效的是生产环境,跟下边mode设置的环境没有关系,我们需要手动更能该nodejs环境变量
                  /* browserslist 要 写在package.json 中
                    "browserslist": {
                        开发环境
                        "development": [
                        "last 1 chrome version",
                        "last 1 firefox version",
                        "last 1 safari version"
                        ],
                        生产环境
                        "production": [
                        ">0.2%",
                        "not dead",
                        "not op_mini all"
                        ]
                    }
                  */
                    {
                        loader: "postcss-loader",
                        options: {
                          postcssOptions: {
                            plugins: [
                              [
                                "postcss-preset-env",
                                {
                                  // 其他选项
                                },
                              ],
                            ],
                          },
                        },
                    }
              ]
          },
          {
              test:/\.less$/,
              use:[
                MiniCssExtractPlugin.loader,
                'css-loader',
                'less-loader'
              ]
          }
      ]
  },
  plugins:[
    new HtmlWebpackPlugin({
        template:'./src/index.html'
    }),
    // mini-css-extract-plugin 这个插件可以将css单独抽离出来需要先下载
    new MiniCssExtractPlugin({
        // 对文件进行重命名
        filename:'css/built.css'
    })
  ],
  mode:'development',
}

7.2.4、压缩css

//webpack.config.js
 
// 压缩css的插件
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin')
 
plugins:[
    new OptimizeCssAssetsPlugin()
]

7.2.5、js兼容性处理

module:[
    rules:[
        //   js兼容性处理:babel-loader (需要下载 babel-loader , @babel/core 和 @babel/preset-env )
        // 1、基本js兼容性处理 --》@babel/preset-env
        //   问题:只能转换基本语法,如promise不能转换
        // 2、全部js兼容处理 --》 @babel/polyfill  下载之后直接在js顶部 import 引入即可(不采用)
        //   问题:我只要解决部分兼容性问题,但是将所有兼容性代码全部引入,体积太大了
        // 3、需要做兼容性处理的按需加载:core-js (需要下载)
        {
            test:/\.js$/,
            loader:'babel-loader',
            // 排除第三方库
            exclude:/node_modules/,
            options:{
                // 预设:指示babel做怎么样的兼容性处理
                presets:[
                    [
                        '@babel/preset-env',
                        {
                            // 按需加载
                            useBuiltIns:'usage',
                            // 指定core-js版本
                            corejs: {
                                version: 3
                            },
                            // 指定兼容性做到哪个版本浏览器
                            targets:{
                                chrome: '60',
                                firefox: '60',
                                ie: '9',
                                safari: '10',
                                edge: '17'
                            }
                        }
                    ]
                ]
            }
        }
    ]
]

7.2.6、js / html 压缩

module.exports={
  plugins:[
    // 压缩打包后生成的html文件
    new HtmlWebpackPlugin({
        template:'./src/index.html',
        minify:{
            // 移除空格
            collapseWhitespace: true,
            // 移除注释
            removeComments:true
        }
    })
  ],
  // 将模式改为生产环境会自动压缩js
  mode:'production',
}

7.2.7、开启HMR功能

// HMR:hot modulereplacement 热模块替换 / 模块热替换
// 作用: 一个模块发生变化,只会重新打包这一个模块(而不是打包所有模块)
//       极大提升构建速度
// css文件:可以使用 HMR 功能, 因为style-loader内部实现了 HMR 功能,
// js文件:默认不能使用 HMR 功能 --》 需要修改js代码,添加支持 HMR 功能的代码
//       只能处理非入口文件的其他js文件
// html文件:默认不能使用 HMR 功能,同时会导致问题:html不能热更新了,
// 解决:修改 entry 入口,讲 html 文件引入, 入口html文件是不需要做热更新的
 
// webpack.config.js
module.exports={
    devServer:{
      contentBase:resolve(__dirname,'build'),
      compress:true,
      port:3000,
      open:true,
      // 开启 HMR 功能
      // 当修改了webpack配置,新配置要想生效必须重启webpack服务
      hot: true
  }
}
 
// index.js
import sub from './util'
 
if(module.hot){
    module.hot.accept('./util.js',function(){
        // 方法会监听 util.js 的文件变化,一旦发生变化,其他默认不会重新打包构建
        // 会执行后边的回调函数1
        sub()
    })
}

7.2.8、优化开发环境调试功能 开启 source-map

// webpack.config.js
module.exports={
    devtool: 'source-map'
}

7.2.9、优化loader 处理性能

// webpack.config.js
 
module.exports={
    module={
        rules:[
                // 只匹配一次,匹配成功后,之后的loader将不会再做匹配
                // 注意:不能有两个配置处理同一种类型的文件
                oneOf:[
                    {
                        test:/\.css$/,
                        use:[
                            'style-loader',
                            'css-loader'
                        ]
                    }
                ]
        ]
    }
}

7.2.10、缓存处理

module.exports={
    module:{
        rules:[
            {
            test:/\.js$/,
            loader:'babel-loader',
            // 排除第三方库
            exclude:/node_modules/,
            options:{
                // 预设:指示babel做怎么样的兼容性处理
                presets:[
                    ...
                ],
                
                // 开启 babel 缓存
                // 第二次构建时,会读取之前的缓存
                cacheDirectory: true
            }
        }
        ]
    }
}

本文转载自: https://blog.csdn.net/zhaoyifei01/article/details/129371377
版权归原作者 zhaoyifei01 所有, 如有侵权,请联系我们删除。

“webpack打包教程”的评论:

还没有评论