A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© charcoal 中级黑马   /  2021-7-10 22:20  /  1686 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

前言日常开发者中,我们常常在用诸如vue-clicreate-react-app的脚手架来构建我们的项目。但是如果你想在团队脱颖而出(鹤立鸡群)、拿到更好的offer(还房贷),那么你必须去深刻的认识下我们经常打交道的webpack


1 入门(一起来用这些小例子让你熟悉webpack的配置)1.1 初始化项目
新建一个目录,初始化npm
需要npm init
webpack是运行在node环境中的,我们需要安装以下两个npm包
下包:pm i -D webpack webpack-cli
  • npm i -D 为npm install --save-dev的缩写
  • npm i -S 为npm install --save的缩写
新建一个文件夹src ,然后新建一个文件main.js,写一点代码测试一下
console.log('这是测试的文字')
配置package.json命令


执行
需要在最外层的目录下进行npm  run  serve
此时如果生成了一个dist文件夹,并且内部含有main.js说明已经打包成功了
1.2 开始我们自己的配置上面一个简单的例子只是webpack自己默认的配置,下面我们要实现更加丰富的自定义配置
新建一个build文件夹,里面新建一个webpack.config.js



[JavaScript] 纯文本查看 复制代码
// webpack.config.js

const path = require('path');
module.exports = {
    mode:'development', // 开发模式
    entry: path.resolve(__dirname,'../src/main.js'),    // 入口文件
    output: {
        filename: 'output.js',      // 打包后的文件名称
        path: path.resolve(__dirname,'../dist')  // 打包后的目录
    }
}

更改我们的打包命令

执行 npm run build会发现生成了以下目录(图片)
其中dist文件夹中的main.js就是我们需要在浏览器中实际运行的文件
当然实际运用中不会仅仅如此,下面让我们通过实际案例带你快速入手webpack

1.3 配置html模板js文件打包好了,但是我们不可能每次在html文件中手动引入打包好的js

可以这样配置打包名称
[JavaScript] 纯文本查看 复制代码
module.exports = {
    // 省略其他配置
    output: {
      filename: '[name].[hash:8].js',      // 打包后的文件名称
      path: path.resolve(__dirname,'../dist')  // 打包后的目录
    }
}


这时候生成的dist目录文件如下

为了缓存,你会发现打包好的js文件的名称每次都不一样。webpack打包出来的js文件我们需要引入到html中,但是每次我们都手动修改js文件名显得很麻烦,因此我们需要一个插件来帮我们完成这件事情
npm i -D html-webpack-plugin


新建一个build同级的文件夹public,里面新建一个index.html
具体配置文件如下
[JavaScript] 纯文本查看 复制代码
// webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
    mode:'development', // 开发模式
    entry: path.resolve(__dirname,'../src/main.js'),    // 入口文件
    output: {
      filename: '[name].[hash:8].js',      // 打包后的文件名称
      path: path.resolve(__dirname,'../dist')  // 打包后的目录
    },
    plugins:[
      new HtmlWebpackPlugin({
        template:path.resolve(__dirname,'../public/index.html')
      })
    ]
}

生成目录如下(图片)

可以发现打包生成的js文件已经被自动引入html文件中
1.3.1 多入口文件如何开发
生成多个html-webpack-plugin实例来解决这个问题
[JavaScript] 纯文本查看 复制代码
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
    mode:'development', // 开发模式
    entry: {
      main:path.resolve(__dirname,'../src/main.js'),
      header:path.resolve(__dirname,'../src/header.js')
  }, 
    output: {
      filename: '[name].[hash:8].js',      // 打包后的文件名称
      path: path.resolve(__dirname,'../dist')  // 打包后的目录
    },
    plugins:[
      new HtmlWebpackPlugin({
        template:path.resolve(__dirname,'../public/index.html'),
        filename:'index.html',
        chunks:['main'] // 与入口文件对应的模块名
      }),
      new HtmlWebpackPlugin({
        template:path.resolve(__dirname,'../public/header.html'),
        filename:'header.html',
        chunks:['header'] // 与入口文件对应的模块名
      }),
    ]
}


此时会发现生成以下目录


1.3.2 clean-webpack-plugin
每次执行npm run build 会发现dist文件夹里会残留上次打包的文件,这里我们推荐一个plugin来帮我们在打包输出前清空文件夹clean-webpack-plugin

[JavaScript] 纯文本查看 复制代码
const {CleanWebpackPlugin} = require('clean-webpack-plugin')
module.exports = {
    // ...省略其他配置
    plugins:[new CleanWebpackPlugin()]
}
1.4 引用CSS
我们的入口文件是js,所以我们在入口js中引入我们的css文件

同时我们也需要一些loader来解析我们的css文件
npm i -D style-loader css-loader
如果我们使用less来构建样式,则需要多安装两个
npm i -D less less-loader
配置文件如下
[JavaScript] 纯文本查看 复制代码
// webpack.config.js
module.exports = {
    // ...省略其他配置
    module:{
      rules:[
        {
          test:/\.css$/,
          use:['style-loader','css-loader'] // 从右向左解析原则
        },
        {
          test:/\.less$/,
          use:['style-loader','css-loader','less-loader'] // 从右向左解析原则
        }
      ]
    }
} 

浏览器打开html如下

1.4.1 为css添加浏览器前缀
npm i -D postcss-loader autoprefixer  
配置一下
[JavaScript] 纯文本查看 复制代码
// webpack.config.js
module.exports = {
    module:{
        rules:[
            {
                test:/\.less$/,
                use:['style-loader','css-loader','postcss-loader','less-loader'] // 从右向左解析原则
           }
        ]
    }
} 

接下来,我们还需要引入autoprefixer使其生效,这里有两种方式
1,在项目根目录下创建一个postcss.config.js文件,配置如下:
[JavaScript] 纯文本查看 复制代码
module.exports = {
    plugins: [require('autoprefixer')]  // 引用该插件即可了
}

2,直接在webpack.config.js里配置
[JavaScript] 纯文本查看 复制代码
// webpack.config.js
module.exports = {
    //...省略其他配置
    module:{
        rules:[{
            test:/\.less$/,
            use:['style-loader','css-loader',{
                loader:'postcss-loader',
                options:{
                    plugins:[require('autoprefixer')]
                }
            },'less-loader'] // 从右向左解析原则
        }]
    }
}
这时候我们发现css通过style标签的方式添加到了html文件中,但是如果样式文件很多,全部添加到html中,难免显得混乱。这时候我们想用把css拆分出来用外链的形式引入css文件怎么做呢?这时候我们就需要借助插件来帮助我们
1.4.2 拆分css
npm i -D mini-css-extract-plugin

webpack 4.0以前,我们通过extract-text-webpack-plugin插件,把css样式从js文件中提取到单独的css文件中。webpack4.0以后,官方推荐使用mini-css-extract-plugin插件来打包css文件
配置文件如下
[JavaScript] 纯文本查看 复制代码
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
  //...省略其他配置
  module: {
    rules: [
      {
        test: /\.less$/,
        use: [
           MiniCssExtractPlugin.loader,
          'css-loader',
          'less-loader'
        ],
      }
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({
        filename: "[name].[hash].css",
        chunkFilename: "[id].css",
    })
  ]
}

1.4.3 拆分多个css
这里需要说的细一点,上面我们所用到的mini-css-extract-plugin会将所有的css样式合并为一个css文件。如果你想拆分为一一对应的多个css文件,我们需要使用到extract-text-webpack-plugin,而目前mini-css-extract-plugin还不支持此功能。我们需要安装@next版本的extract-text-webpack-plugin
npm i -D extract-text-webpack-plugin@next
[JavaScript] 纯文本查看 复制代码
// webpack.config.js

const path = require('path');
const ExtractTextWebpackPlugin = require('extract-text-webpack-plugin')
let indexLess = new ExtractTextWebpackPlugin('index.less');
let indexCss = new ExtractTextWebpackPlugin('index.css');
module.exports = {
    module:{
      rules:[
        {
          test:/\.css$/,
          use: indexCss.extract({
            use: ['css-loader']
          })
        },
        {
          test:/\.less$/,
          use: indexLess.extract({
            use: ['css-loader','less-loader']
          })
        }
      ]
    },
    plugins:[
      indexLess,
      indexCss
    ]
}

1.5 打包 图片、字体、媒体、等文件
file-loader就是将文件在进行一些处理后(主要是处理文件名和路径、解析文件url),并将文件移动到输出的目录中
url-loader 一般与file-loader搭配使用,功能与 file-loader 类似,如果文件小于限制的大小。则会返回 base64 编码,否则使用 file-loader 将文件移动到输出的目录中

[JavaScript] 纯文本查看 复制代码
// webpack.config.js
module.exports = {
  // 省略其它配置 ...
  module: {
    rules: [
      // ...
      {
        test: /\.(jpe?g|png|gif)$/i, //图片文件
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 10240,
              fallback: {
                loader: 'file-loader',
                options: {
                    name: 'img/[name].[hash:8].[ext]'
                }
              }
            }
          }
        ]
      },
      {
        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, //媒体文件
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 10240,
              fallback: {
                loader: 'file-loader',
                options: {
                  name: 'media/[name].[hash:8].[ext]'
                }
              }
            }
          }
        ]
      },
      {
        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/i, // 字体
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 10240,
              fallback: {
                loader: 'file-loader',
                options: {
                  name: 'fonts/[name].[hash:8].[ext]'
                }
              }
            }
          }
        ]
      },
    ]
  }
}

1.6 用babel转义js文件
为了使我们的js代码兼容更多的环境我们需要安装依赖
[JavaScript] 纯文本查看 复制代码
npm i -D babel-loader @babel/preset-env @babel/core
  • 注意 babel-loader与babel-core的版本对应关系
  • babel-loader 8.x 对应babel-core 7.x
  • babel-loader 7.x 对应babel-core 6.x
    配置如下
[JavaScript] 纯文本查看 复制代码
// webpack.config.js
module.exports = {
    // 省略其它配置 ...
    module:{
        rules:[
          {
            test:/\.js$/,
            use:{
              loader:'babel-loader',
              options:{
                presets:['@babel/preset-env']
              }
            },
            exclude:/node_modules/
          },
       ]
    }
}


上面的babel-loader只会将 ES6/7/8语法转换为ES5语法,但是对新api并不会转换 例如(promise、Generator、Set、Maps、Proxy等)
此时我们需要借助babel-polyfill来帮助我们转换
[JavaScript] 纯文本查看 复制代码
npm i @babel/polyfill

[JavaScript] 纯文本查看 复制代码
// webpack.config.js
const path = require('path')
module.exports = {
    entry: ["@babel/polyfill",path.resolve(__dirname,'../src/index.js')],    // 入口文件
}












0 个回复

您需要登录后才可以回帖 登录 | 加入黑马