Webpack

50 阅读4分钟

安装webpack

npm init -y

npm install webpack webpack-cli --save-dev

npx webpack --help//查询相关option

npx webpack//打包

使用webpack插件

npm insatll html-webpack-plugin -D

使用npm webpack --watch(观察模式watch mode)自动监听变化编译

安装devServer npm webpack-dev-server -D npx webpack-dev-server --open

安装css-loadernpm install css-loader -D 安装使loader把css放置在页面上 npm install style-loader -D 对less文件打包npm install less-loader less -D 打包css文件并link引用npm install mini-css-extract-plugin -D基于webpack5 压缩生成的css文件 npm install css-minimizer-webpack-plugin -D

加载xml、csv文件 npm install csv-loader xml-loader -D 加载toml、yaml、json5 npm install json5 yaml toml -D

使用babel-loader使低版本浏览器能解析ES6语法 npm install -D babel-loader @babel/core @babel/preset-env babel-loader:在webpack里应用babel解析ES6的桥梁 @babel/core:babel核心模块 @babel/preset-env:babel预设,一组babel插件的集合 编译时显示regeneratorRuntime is not defined regeneratorRuntime是webpack打包生成的全局辅助函数,由babel生成,用于兼容async/await的语法 解决:npm install --save @babel/runtime包含了regeneratorRuntime npm install --save-dev @babel/plugin-transform-runtime这个插件会在需要regeneratorRuntime的地方自动require导包

在production环境压缩 npm install terser-webpack-plugin -D

书写webpack.config.js文件来设置配置项

const path=require('path') 
//引入插件
const HtmlWebpackPlugin=require('html-webpack-plugin')
const MiniCssExtractPlugin=require('mini-css-extract-plugin')
const CssMinimizerPlugin=require('css-minimizer-webpack-plugin')
const TerserPlugin=require('terser-webpack-plugin')
//自定义JSON 模块parse
const toml=require('toml')
const yaml=require('yaml')
const json5=require('json5')

module.exports={
entry:'./src/index.js',

output:{//导出配置
filename:'scripts/[name].[contenthash].bundle.js',//文件更新浏览器使用新文件而非缓存,放置同一目录下
path:path.resolve(__dirname,'./dist'),
clean:true//每次打包删除上次生成的
assetModuleFilename:'images/test.png'
publicPath:'http://localhost:8080/'
},

mode:'none'/'development'/'production',

devtool:'inline-source-map',//编译后的代码映射回原始源代码

plugins:[
new HtmlWebpackPlugin({
template:'.index.html',//参考模板
filename:'app.html',//导出html位置
inject:'body'//放入位置
}),
new MiniCssExtractPlugin({
    filename:'styles/[contenthash].css'
}),

],

devServer:{//实现热加载及自动刷新,并且将生成文件存入内存
static:'./dist'//将dist目录下的文件作为web服务的根目录
}
}

//资源模块:asset/resource asset/inline asset/source asset
module:{
    rules:[{
    test:'/\.png$/', //正则表达式匹配,符合的资源就会被打包成URL
    type:'asset/resource',
    generator:{//设置生成路径,还可以在output内设置,但优先级低于generator
    filename:'images/[contenthash][ext]'//文件名对应的哈希码+后缀名
    }
    },{
    test:'/\.svg$/', 
    type:'asset/inline',//符合的资源就会被打包成Data URL base64的格式
    },{
    test:'/\.txt$/', 
    type:'asset/source',//符合的资源就会被打包成源代码
    },{
    test:'/\.jpg$/', 
    type:'asset',//符合的资源根据条件选择被打包成Data URL base64的格式或URL
    parser:{
        dataUrlCondition:{
            maxSize:4*1024*1024 //设置打包为Data URL base64的格式的要求为小于4M
        }
      }
    },{
    test:'/\(.css|.less)$/', 
    use:['style-loader','css-loader','less-loader']//有顺序要求,css-loader识别打包文件后,再放置样式(从后往前)
    //当使用mini-css-extract-plugin时
    use:['MiniCssExtractPlugin.loader','css-loader','less-loader']
    },{
    type:/\.(woff|woff2|eot|ttf|otf)$/,//对iconfont使用`
    type:'asset/resource'
    },{
    test:/\.(csv|tsv)$/,
    use:'csv-loader'
    },{
    test:/\.xml$/,
    use:'xml-loader'
    },{
    test:/\.toml$/,
    type:'json',
    psrser:{
     parse:toml.parse
    }
    },{
    test:/\.yaml$/,
    type:'json',
    psrser:{
     parse:yaml.parse
    }
    },{
    test:/\.json5$/,
    type:'json',
    psrser:{
     parse:json5.parse
    }
    },{
    test:/\.js$/,
    exclude:/node_modules/,//排除node_modules内的js代码
    use:{
      loader:'babel-loader',
      options:{
       presets:['@babel/preset-env'],
       plugins:[
         [
           '@babel/plugin-transform-runtime'
         ]
       ]
      }
    }
    }]
},

optimization:{
    minimizer:[
    new CssMinimizerPlugin()
    new TerserPlugin()
    ]
}
}

载入字体文件font @font-face{ font-family:'iconfont'; src:('./assets/iconfont.ttf').format('truetype'); } .icon{ font-family:'iconfont', font-size:4px; } span.classList.add('icon') span.innerHTML='' //设置字体编号

代码分离

image.png

//入口起点 有可能重复引入相同的模块

module.exports={
entry:{
   index: './src/index.js',
   another:'./src/another-modules.js'
   },
output:{//导出配置
    filename:'[name].bundle.js',
    path:path.resolve(__dirname,'./dist'),
    clean:true//每次打包删除上次生成的
    },
}

解决重复引入相同的模块:

module.exports={
entry:{
   index: {
      import:'./src/index.js'
      dependOn:'shared'
   }
   another:{
       import:'./src/another-modules.js'
       dependOn:'shared'
   },
   shared:'lodash' //当上两个模块内有loadsh模块时,抽离出名为shared的chunk
 }
 output:{//导出配置
    filename:'[name].bundle.js',
    path:path.resolve(__dirname,'./dist'),
    clean:true//每次打包删除上次生成的
    },
动态导入:entry:{
   index: './src/index.js',
   another:'./src/another-modules.js'
   },
output:{//导出配置
    filename:'[name].bundle.js',
    path:path.resolve(__dirname,'./dist'),
    clean:true//每次打包删除上次生成的
    },
    .....
    optimization:{
      splitChunks:{//插件自动对公共代码抽离
        cacheGroups:{
          vendor:{
              test:/[\\/]node_modules[\\/]/,//缓存第三方的包
              name:'vendors',
              chunks:'all'
          }
        }
      }
    }
}

动态导入 懒加载

function get(){
    return import(/* webpackChunkName:'math',webpackPrefetch:true */'lodash').then(({
        default:_
    })=>{
         const el=document.creatElement('div')
         el.innerHTML=_.join(['Hello','webpack'],' ')
    })
    return el
}

/* webpackChunkName:'math' */ 导出的名字

/* webpackPrefetch:true */ 预加载,网页空闲时自动加载

环境配置 环境变量 npx webbpack --env production

module.export=(env)=>{ return { .... mode:env.production?'production':'development', } } 划分不同环境的webpack.config.env.js,打包指定环境的文件npx webpack -c 路径

npm脚本 package.json内的 "scripts":{ "start":"webpack serve -c dev路径" "build":"webpack -c prod路径" }

提取公共配置 1.提取重复的配置代码在新文件 webpack.config.common.js 2.将webpack.config.dev.js和webpack.config.prod.js中的重复代码删除,只保留不同的部分 3.使用webpack-merge合并 3.1npm install webpack-merge -D 3.2创建新文件 webpack.config.js 3.3 webpack.config.js内容:

const {merge}=require('webpack-merge')
const commonConfig=require('./webpack.config.common')
const productionConfig=require('./ webpack.config.prod')
const developmentConfig=require(' webpack.config.dev')

module.exports=(env)=>{
    switch(env){
      case env[development]:return merge(commonConfig,developmentConfig)
      case env[production]:return merge(commonConfig,productionConfig)
      default:return new Erroe('')
    }
}

4.设置脚本 "scripts":{ "start":"webpack serve -c ./config/webpack.config.js --env developmment" "build":"webpack -c ./config/webpack.config.js --env production" }