入门Webpack4.x详解

2,071 阅读7分钟

前言

webpack是当下最热门的前端资源模块化管理和打包工具,它可以将许多松散的模块按照依赖和规则打包成符号生产环境部署的前端资源,还可以将按需加载的模块进行代码分割。本篇将介绍webpack的配置、配置Html模板、引入CSS文件等

什么是webpack?

webpack可以看做是模拟打包机:它做的事情是,分析你的项目结构,找到JavaScript模块以及其他的一些浏览器不能直接运行的拓展语言(Scss,TypeScript等),并将其打包为合适的格式以供浏览器使用

webpack可以做哪些事?

  • 代码的转换(比如把es6转换成es5,把less转换成sass)
  • 文件优化(比如在打包的过程中,压缩代码体积,合并文件等)
  • 代码分割(比如在开发多页面的时候,公共页面的抽离,路由懒加载的功能)
  • 模块合并(比如把多个模块合并成一个模块)
  • 自动刷新(帮我们启动一个本地服务,来实现代码变更后可以更新我们的页面)
  • 代码效验(校验我们的代码是否符合规范)
  • 自动发布(打包完成后可以实现一个自动完成的功能,把打包后的代码发布到服务器上)

webpack的基础配置

桌面建webpack文件夹

mkdir webpack

初始化项目

yarn init -y

初始化项目就生成了package.json文件

安装依赖

yarn add webpack webpack-cli -D

启动devServer需要安装一下webpack-dev-server

yarn add webpack-dev-server -D

新建src文件夹

mkdir src

src里新建index.js文件

touch index.js

webpack可以进行零配置

  • 打包工具,把JS模块进行打包然后输出
  • 打包支持JS的模块化

在使用webpack进行打包的时候,默认情况下会将src下的入口文件index.js进行打包

在不设置mode的情况下,打包出来的文件自动压缩

npx webpack

设置mode为开发模式,打包后的文件不被压缩

npx webpack --mode development

注:

  • node v8.2版本以后都会有一个npx
  • npx会执行bin里面的文件

当执行npx webpack命令的时候,webpack会自动查找项目中src目录下的index.js文件,然后进行打包,生成一个dist目录并存在一个打包好的main.js文件

生成目录

配置webpack.config.js

新建webpack.config.js文件

在webpack项目下新建一个webpack.config.js文件

异步默认配置文件的名字是webpack.config.js

//webpack是node写出来的node的写法
let path = require('path')
module.exports = {
    mode: 'development',//模式 默认两种 production development开发模式
    entry: './src/index.js',//入口文件
    output:{
        filename:'bundle.js',//打包后的文件名
        path: path.resolve('dist')//路径必须是一个绝对路径,当前目录下产生一个dist目录
    }
}

打包后项目目录

配置脚本

如果觉得命名太长了,就到package.json里面配置一些脚本

  "scripts": {
    "build": "webpack --config webpack.config.js",
    "dev": "webpack-dev-server"
  },

这里的--config指的是添加配置文件,webpack.config.js文件名

执行npm run build就是我们打包后的文件,这是生产环境下、上线需要的文件

执行npm run dev 是我们开发环境下的文件

配置入口文件的类型

单入口和单出口

entry:'./src/index.js'

多入口和单出口

有的时候我们有多个页面,就需要使用多个出口

entry:['./src/index.js','./src/other.js']

多入口和多出口

//webpack是node写出来的node的写法
let path = require('path');

module.exports = {
    entry: {
        index: './src/index.js',
        other:'./src/other.js'
    },
    output:{
        filename: '[name].js',
        path: path.resolve('dist')
    },
}

这个时候npm run build,就会看到两个打包好的JS文件

配置HTML模板

安装插件

yarn add html-webpack-plugin -D

新建index.html

在src目录下边新建一个index.html文件

touch index.html

单页面开发

再webpack.config.js里面引用

//webpack是node写出来的node的写法
let path = require('path');
let HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    entry: './src/index.js',//入口文件
    output: {
        // 添加hash可以防止文件缓存,每次都会生成4位的hash串
        filename: 'bundle.[hash:4].js',   
        path: path.resolve('dist')
    },
    plugins: [
        // 通过new一下这个类来使用插件
        new HtmlWebpackPlugin({
            // 在src目录下创建一个index.html
            template: './src/index.html',
            hash: true, // 会在打包好的bundle.js后面加上hash串
        })
    ]
}

执行

接着npm run build执行一下

打包后自动引入JS

多页面开发

开发的时候有时候不止一个页面,会要配置多个页面

我们把之前的dist目录删掉

再webpack.config.js里面引用

//webpack是node写出来的node的写法
let path = require('path');
let HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    // 多页面开发,怎么配置多页面
    entry: {
        index: './src/index.js',
        other: './src/other.js'
    },
    // 出口文件  
    output: {                       
        filename: '[name].js',
        path: path.resolve('dist')
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './src/index.html',   
            filename: 'index.html',
            chunks: ['index']   // 对应关系,index.js对应的是index.html
        }),
        new HtmlWebpackPlugin({
            template: './src/other.html',
            filename: 'other.html',
            chunks: ['other']   // 对应关系,login.js对应的是login.html
        })
    ]
}

执行

接着npm run build执行一下,就会看到dist目录下边多了两个文件

配置CSS模块

安装

yarn add style-loader css-loader -D

yarn add less less-loader -D

新建文件

  • 在src目录下 新建一个style.css文件
  • 在src目录下 新建一个style.less文件

src/index.js

import './style.css'; 
import './style.less'; 

webpack.config.js

//webpack是node写出来的node的写法
let path = require('path');

// webpack.config.js
module.exports = {
    entry: {
        index: './src/index.js'
    },
    output: {
        filename: 'bundle.js',
        path: path.resolve('dist')
    },
    module: {
        rules: [
            {
                test: /\.css$/,     // 解析css
                use: ['style-loader', 'css-loader'] // 从右向左解析
            }
        ]
    }
}

接着npm run build执行一下

执行后目录截图

拆分单个CSS

安装

yarn add mini-css-extract-plugin -D

新建文件

  • src文件下边新建css文件和less文件
  • css文件下边新建style.css文件
  • less文件下边新建style.less文件

index.js

import './css/style.css'; 
import './less/style.less'; 

webpack.config.js

let MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
    module: {
        rules: [
            {
                test: /\.css$/,
                use: [MiniCssExtractPlugin.loader, 'css-loader']
            }
        ]
    },
    plugins: [
        new MiniCssExtractPlugin({
            filename: 'css/ming.css'
        })
    ]
}

执行后目录截图

拆分多个css

index.js

import './css/style.css'; 
import './css/reset.less'; 

webpack.config,js

let ExtractTextWebpackPlugin = require('extract-text-webpack-plugin');
let styleLess = new ExtractTextWebpackPlugin('css/style.css');
let resetCss = new ExtractTextWebpackPlugin('css/reset.css');

module.exports = {
    module: {
        rules: [
            {
                test: /\.css$/,
                use: resetCss.extract({
                    use: 'css-loader'
                })
            },
            {
                test: /\.less$/,
                use: styleLess.extract({
                    use: 'css-loader'
                })
            }
        ]
    },
    plugins: [
        styleLess,
        resetCss
    ]
}

执行后目录截图

引入图片打包

安装

yarn add file-loader url-loader -D

file-loader默认会在内部生成一张图片 到build目录下 url-loader是通过base64编码的方法来展示图片

JS创建图片引入

src/index.js

import logo from './logo.jpg'//把图片引入,返回的结果是一个新的图片地址
let image = new Image();
image.src = './logo.jpg'//就是一个普通的字符串
document.body.appendChild(image);

webpack.config.js

 {
    test:/\.(jpg|png|gif|svg)$/,
    use:'url-loader',
    include:path.join(__dirname,'./src'),
    exclude:/node_modules/
  }

页面img引用图片

安装

yarn add html-withimg-loader -D

src/index.css

div{
    width: 952px;height: 249px;
    background: url("./logo.jpg")
}

src/index.js

import './index.css'

webpack.config.js

 rules:[
            {
                test: /\.(png|jpg|gif)$/,
                use: 'file-loader'
            },
    ]

引入字体图片和svg图片

webpack.config.js

rules:[
            {
                test: /\.(png|jpg|gif)$/,
                //做一个限制,当我们的图片,小于多少k的生活,用base64来转化
                //否则用file-loader产生真实图片
                use: 'url-loader',
                options:{
                	limit: 200*1024
                }
            },
       ]

src/index.js

<img src="./logo.jpg" alt="">

添加CSS3属性前缀

为了浏览器的兼容性,有时候我们必须加上一些前缀

安装

yarn add postcss-loader autoprefixer -D

创建postcss.config.js文件

module.exports = {
    plugins: [require('autoprefixer')]  // 引用该插件
}

webpack.config.js配置

module.exports = {
    module: {
        rules: [
            {
                test: /\.css$/,
                use: ['style-loader', 'css-loader', 'postcss-loader']
            }
        ]
    }
}

转成es6语法

Babel会将ES6的代码转成ES5的代码

安装

yarn add babel-core babel-loader babel-preset-env babel-preset-stage-0 -D

webpack.config.js

module.exports ={
    module:{
        rules:[
        {
                test:/\.js$/,
                use:{
                    loader:'babel-loader',
                    options:{//用babel-loader 需要把es6转换成es5
                        presets:[
                            '@babel/preset-env'
                        ]
                    }
                }
            },
        }
    }

服务器配置

webpack.config.js里添加

devServer: {//开发服务器的配置
        host: 'localhost', //默认是localhost
        port: 3000,//端口
        progress: true,//希望在内存中打包看到一个进度条
        contentBase:'./build',//希望./build目录作为静态目录
        compress: true
    },

配置source-map

webpack.config.js添加

源码调试,会单独生成一个sourcemap文件 出错了 表示 当前报错的列和行

devtool: 'source-map'   //添加映射文件,可以帮我们调试源代码

不会参数单独的文件,但是可以显示行和列

devtool:'eval-source-map',

不会参数列,但是是一个单独的映射文件

devtool: 'cheap-module-source-map' //产生后你可以保留起来

不会产生文件,集成在打包后的文件中,不会参数列

devtool:'cheap-module-eval-source-map'

打包前清除输出目录

安装

yarn add clean-webpack-plugin -D

webpack.config.js添加

let CleanWebpackPlugin = require('clean-webpack-plugin');

module.exports = {
    plugins: [
        new CleanWebpackPlugin('dist')  
    ]
}

热更新

以前每次页面更新都要重新更新,热更新是只更新某个部分

代码编写

devServer:{
	hot: true,
}

plugins:[
	//热更新插件
  new webpack.NamedModulesPlugin(),//打印更新的模块路径
  new webpack.HotModuleReplacementPlugin() //热更新插件
]

resolve属性的配置

resolve常用来配置别名和省略后缀名

代码编写

resolve:{//解析 第三方包
        modules:[path.resolve('node_modules')],
        extensions:['.js','.css','.json','.vue'],
        
        mainFiles:[],//入口文件的名字index.js
            alias:{//别名
             bootstrap:'bootstrap/dist/css/bootstrap.css'
        }
    },

抽离公共代码

在多个页面中抽取页面的代码

代码编写

module.exports = {
    //优化
    optimization:{
        splitChunks:{
            //分离代码块
            cacheGroups:{
                //缓存组
                common:{
                    //公共的模块
                    chunks: 'initial',
                    minSize:0,
                    minChunks:2,
                },
                vendor:{
                    priority:1,
                    test:/node_modules/,//把你抽离出来
                    chunks: 'initial',
                    minSize: 0,
                    minChunks: 2,
                }
            }
        }
    },
}

webpack自带优化

  • import 在生产环境下 会自动去除掉没用的代码

  • tree-shaking 把没用的代码 自动删除掉

  • es6模块会把结果放在defalut上

  • scope hosting作用域提升