webpack学习---基础配置篇

webpack:模块打包机

webpack安装:推荐在项目内本地安装,不推荐使用全局安装。

如果配置文件的名字不是webpack.config.js的话,在使用npx webpack进行打包的时候要npx webpack --config 自定义的配置文件名字

webpack-cli的作用:可以使我们在命令行中运行webpack这个指令,如果不安装webpack-cli,则在命令行中运行webpack指令会报错。

webpack配置

webpack可以0配置:不需要写任何配置文件,直接运行npx webpack

打包指令为npx webpack此时打包的是src目录下的index.js文件,打包生成的是和src文件同级的dist文件下的main.js文件。

:打包是为了支持js的模块化,如果在index.js中使用了Common.js的语法规范,即通过require的方式引入了一个模块,本来index.js是无法运行在浏览器环境下的,通过打包之后生成的main.js就可以运行在浏览器环境下了。

通过配置文件来进行配置

默认的webpack的配置文件名为webpack.config.js

下面是一个配置文件的基本结构

let HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports={
    //模式:可以选择是生产模式或者是开发模式,在生产模式下,打包的js文件会被压缩。
    mode:'development',

    //打包文件的入口地址
    entry:path.resolve(__dirname,'./index.js'),

    //打包文件的出口地址
    output:{
        path:path.resolve(__dirname,'dist'),//打包文件将来存放的地址,这个地址必须是一个绝对地址。这里会新生成一个dist目录。打包出来的文件就在这个文件夹下面。
        filename:'bundle.js'//打包后输出的文件名字。
    }

    //开发服务器的配置,也就是webpack-dev-server的配置
    devServer:{
        port:3000//端口号
        contentBase:path.resolve(__dirname,'dist')//指定托管到电脑的内存中的路径
        open:true//自动打开浏览器
    }

    //这里放着webpack的所有插件
    plugins:[
        new HtmlWebpackPlugin({
            template:''//模板对象,一般是src目录下的index.html
            filename:'index.html'//在内存中生成的文件名字
        })
    ]

    //这里放着所有的模块
    module:{
        rules:[//规则
            //css-loader是解析@import这种语法的
            //style-loader是把css文件插入到head标签中
            //loader的特点是希望用途单一
            //loader的顺序默认是从右向左执行。
            {test:/\.css$/,use:['style-loader','css-loader']} //处理css文件的loader
        ]
    }

}

打包其他格式的文件

默认情况下,webpack只能打包js文件,在需要打包其他格式的文件的时候,需要安装对应的loader,并在webpack.config.js中的module中去添加相对应的匹配规则。

loader

作用:Loader直译为”加载器“,webpack将一切文件都看成是模块,但是原声带webpack只能解析js文件,如果其他文件也想被打包的话,就会用到相应的loader,所以loader的作用是让webpack拥有加载和解析非JavaScript文件的能力。

file-loader

module.exports = {
    module:{
        rules:[
            {
                test:/\.(jpg|png|gif)$/,
                use:{
                    loader:'file-loader',
                    options:{
                        name:'[name]_[hash:8].[ext]',//打包的图片的名字是源文件名字_8位hash
                        outputPath:'images/'//打包输出的图片存放在dist目录下的images文件里。
                    }
                }
            }
        ]
    }
}

url-loader

把图片转化为base64的字符串插入到打包的js文件里,减少了依次http请求。缺点是如果打包的文件特别大,生成的base64字符串也会特别大,所以,对于较小的图片,适合使用url-loader,对于较大的图片,还是使用file-loader比较好。

//配置的rules和file-loader及其相似。

module.exports = {
    module:{
        rules:[
            {
                test:/\.(jpg|gif|png)$/,
                use:{
                    loader:'url-loader',
                    options:{
                        name:'[name]_[hash:8].[ext]',
                        outputPath:'images/',
                        limit:5000//这是和file-loader最主要的区别,url-loader在打包图片时,如果图片大小小于配置的limit值,就将图片传化位base64的字符串插入到打包的js文件中,如果大于limit,打包规则就和file-loader一致。所以也可以说url-loader是对file-loader更深层次的包装。
                    }
                }
            }
        ]
    }
}

webpack处理样式相关的文件

打包css文件

  1. npm install style-loader css-loader -D
  2. 添加相应的规则
module.exports = {
    module:{
        rules:[
            {test:/\.css/,use:['style-loader','css-loader']}
        ]
    }
}
//style-loader作用是生成一个<style><style>标签插入在html文件中,css-loader作用是解析@import xxx.cs这种语法。

打包scss文件

  1. npm install style-loader css-loader sass-loader
  2. 添加相应的规则
module.exports = {
    module:{
        rules:[
            {test:/\.scss/,use:['style-loader','css-loader','sass-loader']}
        ]
    }
}


上述处理样式的文件的方法,都会吧css文件直接以<style>标签的形式插入到生成的html文件中,而如果我们希望将css文件打包后单曲抽离出来成为一个文件,且通过link标签的形式引入,就需要这样做:

将css文件抽离出来成为一个单独的文件

  1. npm install mini-css-extract-plugin -D安装相应的插件
  2. 在配置文件中使用这个插件
new MiniCssExtractPlugin({
    filename:'css/main.css'//将抽离出来的css文件会存放在打包时产生的bulid文件夹下的css文件夹下的main.css
})

3.将处理css和less文件的loader中的style-loader替换为MiniCssExtractPlugin.loader

{test:/\.css$/,use:[MiniCssExtractPlugin.loader,'css-loader']},
{test:/\.less$/,use:[MiniCssExtractPlugin.loader,'css-loader','less-loader']}

给css3属性加浏览器前缀

使用的loader是postcss-loader使用的插件是autoprefixer

具体过程如下:

  1. 安装相应的loader和插件
  2. 在根目录下建一个postcss.config.js,里面内容如下:
module.exports={
  plugins:[require('autoprefixer')]
}
  1. 将postcss-loader写在相应的rules里面。(写在处理css文件的css-loader的下面即可)

处理字体图标

  1. 在iconfont字体图标矢量库中选区自己需要的字体图标,下载代码到本地
  2. 将下载下来的代码中的字体文件和iconfont.css文件拷贝到项目中。
  3. 修改webpack.config.js的配置项,新增加一个匹配规则如下:
module.exports = {
    rules:[
        {test:/\.(svg|ttf|eot|woff)$/,use:{
            loader:'file-loader',
            options:{
                outputPath:'./fonts'
            }
        }}
    ]
}
  1. 在项目的index.css文件里通过@import 'iconfont.css'的形式引入字体图标的样式文件。

plugins

作用:Plugin的直译是‘’插件‘’.Plugin可以扩展webpack的功能,让webpack具有更多的灵活性。在webpack运行的生命周期中会广播出来许多事件,plugin可以监听这些事件,在合适的时机通过webpack提供的api改变输出结果。

html-webpack-plugin

作用:在打包结束之后,自动生成一个html文件,并将打包生成的js文件自动引入到这个html文件中。

使用方法:

  1. 下载安装相应的插件npm install html-webpack-plugin -D
  2. 修改配置文件,添加plugins属性
let HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
    plugins:[
        new HtmlWebpackPlugin({
            template:'./src/index.html',//打包后自动生成的html文件的模板
            filename:'index.html'//自动生成的html文件的名字
        })
    ]
}

clean-webpack-plugin

作用:在每次打包之前都会将上一次打包生成的dist目录删除掉。

使用方法:

  1. 安装相应的插件npm install clean-webpack-plugin -D
  2. 修改配置文件,添加相应的plugin

注意
每一次打包的结果中的hash值是随着打包源文件变化而变化的。如果要打包的源文件没有发生变化,那么打包结果的hash值也就不会有变化。但是实际上确实每一次都是删除了dist目录下的文件重新生成新的一份打包文件的。

let {CleanWebpackPlugin} = require('clean-webpack-plugin');
module.exports = {
    plugins:[
        new CleanWebpackPlugin()//在打包之前删除dist目录中的内容。
    ]
}

多入口情况处理

// 多入口
let path = require('path')
let HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
    mode: 'development',
    entry: {
        home: './src/index.js',
        other: './src/other.js'
    },
    output: {
        filename: "[name].js",//这里的name就是entry里面的两个文件,可以是home,也可以是other
        path: path.resolve(__dirname, 'dist2'),
        publicPath:cdn地址//这里再打包完之后,会在html文件引入打包的js文件之前都加入这个cdn
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './index.html',
            filename: 'home.html',
            chunks: ['home']//表示home.html里面引入的是打包生成的home.js
        }),
        new HtmlWebpackPlugin({
            template: './index.html',
            filename: 'other.html',
            chunks: ['other', 'home']   // other.html 里面有 other.js & home.js
        }),
    ]
}

souce-map的配置

作用:源码映射,用于在编码出错时,迅速找到源码的出错地址。

在module.exports导出的对象中加入devtool: 'source-map' // 增加映射文件可以帮我们调试源代码

  1. 「source-map」:源码映射 会标识错误的代码 打包后生成独立的文件 大而全 出错了会标识当前出错的列和行
  2. 「evl-source-map」:不会生成单独的文件 但是可以显示行和列
  3. 「cheap-module-source-map」:不会产生列,产生单独的映射文件 (生产环境线上推荐这个)
  4. 「cheap-module-eval-source-map」:不会产生文件 集成在打包后的文件中 不会产生列 (开发环境推荐使用这个)

watch 监视打包文件,当需要打包的文件发生改变的时候,就自动重新打包

watch: true,
watchOptions: {
    poll: 1000,   // 每秒检查一次变动
    aggregateTimeout: 300,  // 当第一个文件更改,会在重新构建前增加延迟(修改文件防抖)
    ignored: /node_modules/  // 对于某些系统,监听大量文件系统会导致大量的 CPU 或内存占用。这个选项可以排除一些巨大的文件夹,
},

webpack-dev-server的使用

安装:npm install webpack-dev-server -D

配置时就是在module.exports导出的对象中添加一个devServer属性,具体情况如下所示:

module.exports = {
    devServer:{
        contentBase:'./dist',//表示服务器起在这个目录下,因为我们打包生成的目录时dist,所以这里和其保持一致
        port:3000,//表示服务器时开在3000端口上的
        open:true,//自动打开浏览器,
        progress:true//在打包编译的过程中会有一个进度条效果
        proxy:{//这个属性时用来做跨域的。
            '/api':'http://localhost:3000'//当前端的请求是以api开头的,就转到后面的这个地址上。
        }
    }
}

webpack跨域配置

常见的跨域有三种情况,下面分别介绍在这三种情况下如何配置webpack

设置代理:这种情况下,会起一个后端服务

服务端采用express框架搭建,服务端代码如下:

let express = require('express');
let app = express();

情况1:
app.get('/api/user',(req,res)=>{
    res.json({name:'GouKu'});
})

情况2:后端请求并不是以api开头
app.get('/user',(req,res)=>{
    res.json({name:'GouKu'});
})
app.listen(3000,()=>{console.log('app运行在3000端口上')})

webpack默认端口是8080,所以可以在配置文件中设置一个代理

module.exports ={
    devServer:{
        contentBase:'./dist',
        open:true,
        //情况1:
        proxy:{
            '/api':'http://localhost:3000'//表示如果前端i请求的路径是以api开头的,都转到3000这个端口上去。
        }
        //情况2:在这种情况下,虽然前端依然请求的是api/user,但是经过代理之后,给后端发出的请求就是将api删掉了,实际向后端请求的是/user
          proxy:{
            '/api':{
                    target:'http://localhost:3000',
                    reWritePath:{'^/api',''}
                }
        }
    }
}

index.js中是这样写的

let xhr = new XMLHttpRequset();

xhr.open('GET','/api/user',true);//这样每当请求的是以api开头的,就转到3000端口上去
xhr.onload=function(){
    console.log(xhr.response);
}
xhr.send();

只是前端去mock数据,并不涉及到后端

module.exports={
    devServer:{
        contentBase:'./dist',
        before:function(app){//启用一个钩子函数
            app.get('/api/user',(req,res)=>{
                res.json({'name':'GouKu'})
            })
        }
    }
}

有服务端且不使用代理,直接从服务端开启webpack

  1. 首先下载安装webpack的中间键npm install webpack-dev-middleware -D
//server.js的内容如下:

let express = require('express');
let webpack = require('webpack');
let app = express();

let middle = require('webpack-dev-middleware');
let config = require('./webpack.config.js');
let compiler = webpack(config);
app.use(middle(compiler));

app.get('/api/user',(req,res)=>{
    res.json({'name'"GouKu"});
})

app.listen(3000,()=>{console.log('app运行在3000端口上')})


//这样,在访问localhost:3000/api/user时也可以得到数据。    

热模块更新(hot module replacement HMR)

使用热模块更新,可以在不刷新浏览器的情况下,只针对修改的文件做出样式活着是js上的变化。具体使用步骤如下:

  1. 由于webpack自带着针对HMR的插件,所以,我们不必要再额外下载安装插件,只需要引入webpack即可。
  2. 在webpack.config.js中的devServer属性中添加上hot:true
  3. 在webpack.config.js中的plugins属性中实例化这个插件。
const webpack = require('webpack');//setp1
module.exports = {
    devServer:{
        contentBase:'./dist',
        port:3000,
        progress:true,
        open:true,
        hot:true,//step2
    }
    plugins:[
        new webpack.HotModuleReplacementPlugin();//step3
    ]
}

注意

如果修改的是css文件,由于css-loader的关系,不需要在做额外的行为就可以针对修改的css样式浏览器做出反应,如果修改的是js文件,则需要在打包的入口文件中添加上以下代码:

if(module.hot){
    module.hot.accept(修改的js文件,()=>{要执行的变化(业务代码)})
}

webpack利用babel处理ES6语法

  1. 安装相应的loader

npm install --save-dev babel-loader @babel/core

  1. 在rules添加相应的规则
module:{
    rules:[
        {test:/\.js$/,exclude:/node_modules/,use:'babel-loader'}
    ]
}
  1. 在项目根路径下创建一个名字叫.babelrc的文件,里面的内容为
{
    "preset":["@babel/preset-env"]
}

注意:上述做法是babel官网的教程,但是这样的做法是不全面的,更全面的做法是,在上述基础上,接着如下操作:

  1. 安装babel/polyfill npm install --save @babel/polyfill
  2. 在打包的入口js文件导入babel/polyfill import "@babel/polyfill";这样其实就可以了,但是打包出来的js文件会非常大,所以还需要第6步的优化
  3. 修改.babelrc文件为:
{
    "preset":[["@babel/preset-env",{
         targets: {
            edge: "17",
            firefox: "60",
            chrome: "67",
            safari: "11.1",
      },//target里面写的内容是这些版本及以上的的浏览器对ES6语法都做了很好的兼容,所以,不需要再ployfill,就可以减少打包文件的体积。
        useBuiltIns: 'usage'//只有用到的ES6语法方案才会被注入。
    }]]
}

注意:上述的关于babel在webpack上的配置都是用来处理业务代码的,如果在实际开发中我们需要开发的是js类库这种不需要污染全局变量的化,就不能使用babel/polyfill了,而是要采用以下配置

  1. 不需要在入口文件引入import "@babel/polyfill
  2. npm install --save-dev @babel/plugin-transform-runtime
  3. npm install --save @babel/runtime
  4. 修改.babelrc文件如下:
{
  "plugins": [
    [
      "@babel/plugin-transform-runtime",
      {
        "absoluteRuntime": false,
        "corejs": 2,
        "helpers": true,
        "regenerator": true,
        "useESModules": false
      }
    ]
  ]
}
  1. 此时打包的时候会报错,是因为还需要再npm install --save @babel/runtime-corejs2这样就不会报错了。

 上一篇
webpack学习笔记---性能优化篇 webpack学习笔记---性能优化篇
提高webpack的打包速度 尽可能在更少的文件中使用loader,比如在使用babel-loader时,通过exclude来排除掉在node_modules里面的js文件,这样可以提高打包速度。 Plugin尽可能精简并且确保可靠(尽可
下一篇 
git学习笔记 git学习笔记
初始化一个git仓库:git init 添加文件到代码仓库,分两步: 使用命令git add 文件名 —–>把文件修改添加到暂存区 使用命令git commit -m 提示消息 —->把暂存区所有内容提交到当前分支 要随
  目录