Webpack4.x 学习过程

本文详细介绍Webpack 4的配置及使用方法,包括环境搭建、模块热替换、多入口文件设置、CSS及图片等资源加载、ES6转码、开发与生产环境配置分离等内容。

前言

之前一直听说 webpack 的大名,可惜未曾得见。今天有空,初步了解了 Webpack 工作方式后,一步步的开始学习使用 Webpack,并把其中的关键点记录下来

这不是一个教程,是工作当中用到的时候才写的,所有看起来会有点乱

环境配置

  • 需要用到 node 环境,建议依赖node的环境版本>=6.11.5
  • 进入项目初始化 npm init,生成package.json
  • 正常安装 webpack 之外,webpack4 需要再单独安一个 webpack-cli

    npm init
    npm install --save-dev webpack webpack-cli

webpack.config.js

1、创建 webpack.config.js

let path = require('path');
let webpack = require('webpack');

module.exports = {
    mode: "development", // 模式配置 development || production
    entry: '',               // 入口文件
    output: {},              // 出口文件
    module: {},              // 处理对应模块
    plugins: [],             // 对应的插件
    devServer: {},           // development  下开发服务器
}

2、启动静态服务器

如果文件被更新,代码将被重新编译

npm install --save-dev webpack-dev-server

// webpack.config.js
devServer: {
    contentBase: './dist', // 静态文件根目录
    hot: true, // 模块热替换
    overlay: true, // 浏览器页面上显示错误
    stats: "errors-only", // 控制编译的时候shell上的输出内容  minimal || normal || verbose
    compress: true // 服务器返回浏览器的时候是否启动gzip压缩
},
module.exports = {
    plugins: [
        new webpack.NamedModulesPlugin(),
        // 热替换,热替换不是刷新
        new webpack.HotModuleReplacementPlugin()
    ],
}

//package.json
"start": "webpack-dev-server --open",

js中的内容修改保存后,在不刷新页面的情况下直接修改掉,这样就实现了热更新

3、Source Maps 调试

开发中方便的调试能极大的提高开发效率,不过通过打包后的文件,很难找到出错了的地方,Source Maps 就是来帮我们解决这个问题的

// webpack.config.js
devtool: 'inline-source-map' // 有多种选项      

4、Html模板和清空 dist

使用hash值之后,每次打包的文件都不一样,dist里面的文件会越来越多,需要每次打包前清空文件夹
文件都打包好了,但是我们在使用的时候不能在dist目录下去创建一个html文件,然后去引用打包后的js吧,这不合理,实际开发中也不会这样
我们需要实现html打包功能,可以通过一个模板实现打包出引用好路径的html来

npm install --save-dev html-webpack-plugin clean-webpack-plugin 

// webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');

plugins: [
    new CleanWebpackPlugin(['dist']),
    new HtmlWebpackPlugin({
       template: path.resolve(__dirname, 'app', 'index.tmpl.html'),// 源模板文件
        filename:'index.html',  //生成的html存放路径,相对于 path
        minify:{  //压缩HTML文件
            removeComments:true,  //移除HTML中的注释
            collapseWhitespace:false  //删除空白符与换行符
        },
        //chunks:['index', 'vendor'], // 多入口的html文件用chunks这个参数来区分
    })
]

5、多入口文件

entry: {
        index: './src/index.js',
        login: './src/login.js'
    },
    output: {
        // [name]就可以将出口文件名和入口文件名一一对应
        filename: '[name]-[hash].js',      // 打包后会生成index.js和login.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/login.html',
            filename: 'login.html',
            chunks: ['login']   // 对应关系,login.js对应的是login.html
        })
    ]

6、加载 CSS

css文件需要额外的loader支持

npm install --save-dev style-loader css-loader

// webpack.config.js    
  module.exports = {
   module: {
     rules: [
       {
         test: /\.css$/,
         use: [  // 从右向左解析
           'style-loader',
           'css-loader'
         ]
       }
     ]
   }
  };
  
// 在入口文件 main.js 加入:
import './style.css';

打包后的css文件是以行内样式style的标签写进打包后的html页面

7、拆分 css

全部打包到一个文件,太多会影响加载速度,需要把文件拆分

npm install --save-dev mini-css-extract-plugin

 // webpack.config.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); // CSS文件单独提取出来

module: { 
    rules: [
        {
            test: /\.css$/,
            use: [
                // 将 css 用 link 的方式引入就不再需要 style-loader
                MiniCssExtractPlugin.loader,
                "css-loader"
            ],
            include: path.resolve(__dirname, 'app'), // 限制范围,提高打包速度
            exclude: /node_modules/
        },
    ]
}

new MiniCssExtractPlugin({
    filename: `css/[name]-[contenthash].css`,
}),

添加 CSS3 前缀
通过 postcss 中的 autoprefixer 可以实现将 CSS3 中的一些需要兼容写法的属性添加响应的前缀,这样省去我们不少的时间

npm install --save-dev postcss-loader autoprefixer 

在项目根目录下创建一个 postcss.config.js 文件

// postcss.config.js
module.exports = {
    plugins: [require('autoprefixer')]  // 引用该插件即可了
}

// webpack.config.js 
{
    test: /\.css$/,
    use: ['style-loader', 'css-loader', 'postcss-loader']
}

8、加载图片

npm install --save-dev file-loader url-loader

// webpack.config.js  
module: {
  rules: [
   {
        test: /\.(png|svg|jpg|gif)$/,
        //use: ['file-loader']
        use: [
            {
                // url-loader内置了file-loader
                loader: 'url-loader',
                options: {
                    limit: 8192,    // 小于8k的图片自动转成base64格式,并且不会存在实体图片
                    outputPath: 'images/'   // 图片打包后存放的目录
                }
            }
        ]
    },
  ]
 ]
 
// main.js
import Icon from './icon.png';

页面中经常会用到img标签,img引用的图片地址也需要一个loader来帮我们处理好

npm install --save-dev html-withimg-loader
module.exports = {
    module: {
        rules: [
            {
                test: /\.(htm|html)$/,
                use: 'html-withimg-loader'
            }
        ]
    }
}

这样再打包后的html文件下img就可以正常引用图片路径了

svg图片都可以通过file-loader来解析,样式中引入了这类格式的图标或者图片都没有问题了,img如果也引用svg格式的话,配合上面写好的html-withimg-loader就都没有问题了

9、加载字体

file-loader 和 url-loader 可以接收并加载任何文件,然后将其输出到构建目录

// webpack.config.js
 {
     test: /\.(woff|woff2|eot|ttf|otf)$/,
     use: [
       'file-loader'
     ]
   }
   
// style.css
@font-face {
    font-family: 'MyFont';
    src:  url('./Omnes_Light.otf') format('woff2');
    font-weight: 600;
    font-style: normal;
}

10、加载数据

NodeJS,JSON 支持实际上是内置
导入 CSV、TSV 和 XML

npm install --save-dev csv-loader xml-loader

//webpack.config.js
{
    test: /\.(csv|tsv)$/,
    use: [
        'csv-loader'
    ]
},
{
    test: /\.xml$/,
    use: [
        'xml-loader'
    ]
}

// main.js
// 所导入的 Data 变量将包含可直接使用的已解析 JSON
import Data from './data.xml'; // JSON, CSV, TSV, XML

11、模块热替换

css的hash命名必须使用contenthash,保证即使css文件所处的模块里就算其他文件内容改变,只要css文件内容不变,那么不会重复构建

css 如果使用style-loader将样式添加到js文件中,在编写样式的时候可以享受热更新的效果,如果将样式提取,需要手动刷新。

方法二:在入口文件中引入html文件,并使用raw-loader对html文件进行处理,实现html热更新

html自动更新
1、安装raw-loader

npm install --save-dev raw-loader  

2、在webpack.config.js中配置raw-loader

    rules: [  
      ......  
      {  
         test: /\.(htm|html)$/,  
         use: [  
           'raw-loader'  
         ]  
      }  
      ......  
    ] 

3、在入口文件index.js文件中引入index.html文件

import '../template/index.html'  

12、转义 ES6

在实际开发中,经常使用 ES6 去写代码,这样会提高我们写代码的速度,不过为了向后兼容低版本浏览器,需要 Babel 转换成兼容的代码

npm install -save-dev babel-core babel-loader babel-preset-env babel-preset-stage-0 babel-preset-react

代码不仅仅包含ES6还有之后的版本和那些仅仅是草案的内容,所以我们可以通过一个.babelrc文件来配置一下

// .babelrc
{
    "presets": ["env", "stage-0"]   // 从右向左解析
}

// webpack.config.js
module.exports = {
    module: {
        rules: [
            {
                test:/\.js$/,
                use: 'bable-loader',
                include: /src/,          // 只转化src目录下的js
                exclude: /node_modules/  // 排除掉node_modules,优化打包速度
            }
        ]
    }
}

13、构建开发和生产环境-分离配置文件

npm install --save-dev webpack-merge

新建 webpack.common.js、webpack.dev.js、webpack.prod.js
把 webpack.config.js 文件内容分为公共代码、开发代码、生产代码

14、压缩提取出的css,解决分离出的js重复问题

npm install --save-dev optimize-css-assets-webpack-plugin

// webpack.prod.js
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin');

plugins: [
        new OptimizeCSSPlugin({
            cssProcessorOptions: {safe: true}
        }),
    ]
          

15、集中拷贝静态资源

npm install --save-dev copy-webpack-plugin

// webpack.prod.js
const copyWebpackPlugin = require('copy-webpack-plugin');

new copyWebpackPlugin([{

from:__dirname+'/src/public',//打包的静态资源目录地址
to:'./public' //打包到dist下面的public

}]),

16、报错

1、Cannot use [chunkhash] or [contenthash] for chunk in '[name]-[chunkhash].js' (use [hash] instead)
解决方法:

  • 如果是开发环境,将配置文件中入口文件的 chunkhash 替换为 hash
  • 如果是生产环境,不要使用参数 --hot

2、Refusing to install package with name "react" under a package also called "react".
解决方法:package.json name 的值不能跟npm的包名相同,同时把 package-lock.json 的 name 修改

3、img 和 css 的图片路径不对
如果是在css文件里引入的如背景图之类的图片,就需要指定一下相对路径

module: {
        rules: [
            {
                test: /\.css$/,
                use: [
                    {
                        loader: MiniCssExtractPlugin.loader,
                        options: {
                            /*
                            * 复写 css 文件中资源路径
                            * 因为 css 文件中的外链是相对与 css 的,
                            * 我们抽离的 css 文件在可能会单独放在 css 文件夹内
                            * 引用其他如 img/a.png 会寻址错误
                            */
                            publicPath: '../' 
                        }
                    },
                    { loader: "css-loader" },
                    { loader: "postcss-loader" }
                ],
                include: path.resolve(__dirname, 'src'),
                exclude: /node_modules/
            }
        ]
    }

异常情况

这是 webpack4 的一些常规操作 Github
官网

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值