webpack4

webpack4

众所周知,webpack进入第4个大版本已经有2个月的时间了,并且webpack团队升级更新的速度也是很是的惊人css

在写下以下内容的时候webpack已经出到了4.6的版本了,剑指5.0应该是指日可待了,固然这些都是我的的臆想,并不表明任何意见html

既然咱们已经迎接了webpack4的到来了,那么就一块儿来使用一下,即便你没用过以前的版本,不要紧,咱们从新出发,将工做中经常使用到的配置写给你们来看vue

非友情提示:因为webpack使用起来并不能仅看代码就方便理解,因此有图有真相的才是正解,因而乎本文配图不少,真的是不少node

首先,既来之,则安之react

安装webpack

  • 须要先在项目中npm init初始化一下,生成package.json
  • 建议node版本安装到8.2以上
  1.  
    // webpack4中除了正常安装webpack以外,须要再单独安一个webpack-cli
  2.  
     
  3.  
    npm i webpack webpack-cli -D

★ npm i -D 是 npm install --save-dev 的简写,是指安装模块并保存到 package.json 的 devDependencies中,主要在开发环境中的依赖包jquery

0配置了什么

webpack4能够支持0配置打包,这里所说的0配置又是什么呢?固然在开发者眼中0配置的东西,那根本是没法用的,由于不够智能,那么咱们就来看看作到了哪些0配置webpack

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

  1.  
    // node v8.2版本之后都会有一个npx
  2.  
    // npx会执行bin里的文件
  3.  
     
  4.  
    npx webpack // 不设置mode的状况下 打包出来的文件自动压缩
  5.  
     
  6.  
    npx webpack --mode development // 设置mode为开发模式,打包后的文件不被压缩

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

这些算是0配置的操做了,名字都是定义好的,不能变,想一想也很鸡肋json

webpack的使用仍是在咱们的配置方面,下面就进入咱们的常规操做环节

 

webpack是基于Node的

在项目下建立一个webpack.config.js(默认,可修改)文件来配置webpack

  1.  
    module.exports = {
  2.  
    entry: '', // 入口文件
  3.  
    output: {}, // 出口文件
  4.  
    module: {}, // 处理对应模块
  5.  
    plugins: [], // 对应的插件
  6.  
    devServer: {}, // 开发服务器配置
  7.  
    mode: 'development' // 模式配置
  8.  
    }

以上就是webpack的正常配置模块

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

npm i webpack-dev-server -D

 

按照项目的结构,咱们就从0开始去写一下配置吧

 

  1.  
    // webpack.config.js
  2.  
     
  3.  
    const path = require( 'path');
  4.  
     
  5.  
    module.exports = {
  6.  
    entry: './src/index.js', // 入口文件
  7.  
    output: {
  8.  
    filename: 'bundle.js', // 打包后的文件名称
  9.  
    path: path.resolve( 'dist') // 打包后的目录,必须是绝对路径
  10.  
    }
  11.  
    }

上面就能够说是实现了最简单的webpack配置了,那接下来就打包一下看看

 

配置执行文件

工做当中咱们打包编译的时候通常都执行npm run dev这样的命令,既然是经过npm执行的命令,咱们就应该找到package.json里的执行脚本去配置一下命令,这里以下图所示

 

npm run build就是咱们打包后的文件,这是生产环境下,上线须要的文件

 

npm run dev是咱们开发环境下打包的文件,固然因为devServer帮咱们把文件放到内存中了,因此并不会输出打包后的dist文件夹

经过npm run build以后会生成一个dist目录文件夹,就和上面打包后的样子同样了

多入口文件

多个入口能够有两种实现方式进行打包

  • 一种是没有关系的可是要打包到一块儿去的,能够写一个数组,实现多个文件打包
  • 另外一种就是每个文件都单独打包成一个文件的
  • 下面就来看看这两种方式的写法
  1.  
    let path = require('path');
  2.  
     
  3.  
    module.exports = {
  4.  
    // 1.写成数组的方式就能够打出多入口文件,不过这里打包后的文件都合成了一个
  5.  
    // entry: [ './src/index.js', './src/login.js'],
  6.  
    // 2.真正实现多入口和多出口须要写成对象的方式
  7.  
    entry: {
  8.  
    index: './src/index.js',
  9.  
    login: './src/login.js'
  10.  
    },
  11.  
    output: {
  12.  
    // 1. filename: 'bundle.js',
  13.  
    // 2. [name]就能够将出口文件名和入口文件名一一对应
  14.  
    filename: '[name].js', // 打包后会生成index.js和login.js文件
  15.  
    path: path.resolve( 'dist')
  16.  
    }
  17.  
    }

这时候执行npm run build后,会生成打包好的两个js文件,如图所示

 

配置Html模板

文件都打包好了,可是咱们在使用的时候不能在dist目录下去建立一个html文件,而后去引用打包后的js吧,这不合理,实际开发中也不会这样

咱们须要实现html打包功能,能够经过一个模板实现打包出引用好路径的html来

这就须要用到一个经常使用的插件了,html-webpack-plugin,用以前咱们来安一下它

npm i html-webpack-plugin -D

由于是个插件,因此须要在config.js里引用一下的

  1.  
    let path = require('path');
  2.  
    // 插件都是一个类,因此咱们命名的时候尽可能用大写开头
  3.  
    let HtmlWebpackPlugin = require('html-webpack-plugin');
  4.  
     
  5.  
    module.exports = {
  6.  
    entry: './src/index.js',
  7.  
    output: {
  8.  
    // 添加 hash能够防止文件缓存,每次都会生成4位的hash串
  9.  
    filename: 'bundle.[hash:4].js',
  10.  
    path: path.resolve( 'dist')
  11.  
    },
  12.  
    plugins: [
  13.  
    // 经过new一下这个类来使用插件
  14.  
    new HtmlWebpackPlugin({
  15.  
    // 用哪一个html做为模板
  16.  
    // 在src目录下建立一个index.html页面当作模板来用
  17.  
    template: './src/index.html',
  18.  
    hash: true, // 会在打包好的bundle.js后面加上hash串
  19.  
    })
  20.  
    ]
  21.  
    }

经过上面的配置后,咱们再npm run build打包看一下如今是个什么样子了

 

多页面开发,怎么配置多页面

若是开发的时候不仅一个页面,咱们须要配置多页面,那么须要怎么来搞呢?不用担忧,html-webpack-plugin插件自有办法,咱们来观望一下

  1.  
    let path = require('path');
  2.  
    let HtmlWebpackPlugin = require('html-webpack-plugin');
  3.  
     
  4.  
    module.exports = {
  5.  
    // 多页面开发,怎么配置多页面
  6.  
    entry: {
  7.  
    index: './src/index.js',
  8.  
    login: './src/login.js'
  9.  
    },
  10.  
    // 出口文件
  11.  
    output: {
  12.  
    filename: '[name].js',
  13.  
    path: path.resolve( 'dist')
  14.  
    },
  15.  
    plugins: [
  16.  
    new HtmlWebpackPlugin({
  17.  
    template: './src/index.html',
  18.  
    filename: 'index.html',
  19.  
    chunks: [ 'index'] // 对应关系,index.js对应的是index.html
  20.  
    }),
  21.  
    new HtmlWebpackPlugin({
  22.  
    template: './src/login.html',
  23.  
    filename: 'login.html',
  24.  
    chunks: [ 'login'] // 对应关系,login.js对应的是login.html
  25.  
    })
  26.  
    ]
  27.  
    }

继续npm run build看打包后的样子

上面基本介绍完了html和js的打包配置了,如今咱们还缺一个好兄弟css,webpack对css的解析须要用到loader,因此咱们先提早安装好,待会好方便使用

 

引用CSS文件

能够在src/index.js里引入css文件,到时候直接打包到生产目录下

须要下载一些解析css样式的loader

  1.  
    npm i style-loader css-loader -D
  2.  
    // 引入less文件的话,也须要安装对应的loader
  3.  
    npm i less less-loader -D

下面咱们来看一下如何配置css文件的解析

  1.  
    // index.js
  2.  
    import './css/style.css'; // 引入css
  3.  
    import './less/style.less'; // 引入less
  4.  
     
  5.  
    console.log( '这里是打包文件入口-index.js');
  6.  
     
  7.  
    // webpack.config.js
  8.  
    module.exports = {
  9.  
    entry: {
  10.  
    index: './src/index.js'
  11.  
    },
  12.  
    output: {
  13.  
    filename: 'bundle.js',
  14.  
    path: path.resolve( 'dist')
  15.  
    },
  16.  
    module: {
  17.  
    rules: [
  18.  
    {
  19.  
    test: /\.css$/, // 解析css
  20.  
    use: [ 'style-loader', 'css-loader'] // 从右向左解析
  21.  
    /*
  22.  
    也能够这样写,这种方式方便写一些配置参数
  23.  
    use: [
  24.  
    {loader: 'style-loader'},
  25.  
    {loader: 'css-loader'}
  26.  
    ]
  27.  
    */
  28.  
    }
  29.  
    ]
  30.  
    }
  31.  
    }

 

 

  • 此时打包后的css文件是以行内样式style的标签写进打包后的html页面中,若是样式不少的话,咱们更但愿直接用link的方式引入进去,这时候须要把css拆分出来
  • extract-text-webpack-plugin插件相信用过的人都知道它是干什么的,它的功效就在于会将打包到js里的css文件进行一个拆分

拆分CSS

  1.  
    // @next表示能够支持webpack4版本的插件
  2.  
    npm i extract-text-webpack-plugin@next -D
  1.  
    let path = require('path');
  2.  
    let HtmlWebpackPlugin = require('html-webpack-plugin');
  3.  
    // 拆分css样式的插件
  4.  
    let ExtractTextWebpackPlugin = require('extract-text-webpack-plugin');
  5.  
     
  6.  
    module.exports = {
  7.  
    entry: './src/index.js',
  8.  
    output: {
  9.  
    filaneme: 'bundle.js',
  10.  
    path: path.resolve( 'dist')
  11.  
    },
  12.  
    module: {
  13.  
    rules: [
  14.  
    {
  15.  
    test: /\.css$/,
  16.  
    use: ExtractTextWebpackPlugin.extract({
  17.  
    // 将css用link的方式引入就再也不须要style-loader了
  18.  
    use: 'css-loader'
  19.  
    })
  20.  
    }
  21.  
    ]
  22.  
    },
  23.  
    plugins: [
  24.  
    new HtmlWebpackPlugin({
  25.  
    template: './src/index.html',
  26.  
    }),
  27.  
    // 拆分后会把css文件放到dist目录下的css/style.css
  28.  
    new ExtractTextWebpackPlugin( 'css/style.css')
  29.  
    ]
  30.  
    }

此时拆分完css后,打包的html页面就以link的方式去引入css了,这样很好

 

引用图片

  • 处理图片方面,也须要loader
npm i file-loader url-loader -D

若是是在css文件里引入的如背景图之类的图片,就须要指定一下相对路径

  1.  
    module.exports = {
  2.  
    module: {
  3.  
    rules: [
  4.  
    {
  5.  
    test: /\.css$/,
  6.  
    use: ExtractTextWebpackPlugin.extract({
  7.  
    use: 'css-loader',
  8.  
    publicPath: '../'
  9.  
    })
  10.  
    },
  11.  
    {
  12.  
    test: /\.(jpe?g|png|gif)$/,
  13.  
    use: [
  14.  
    {
  15.  
    loader: 'url-loader',
  16.  
    options: {
  17.  
    limit: 8192, // 小于8k的图片自动转成base64格式,而且不会存在实体图片
  18.  
    outputPath: 'images/' // 图片打包后存放的目录
  19.  
    }
  20.  
    }
  21.  
    ]
  22.  
    }
  23.  
    ]
  24.  
    }
  25.  
    }

在css中指定了publicPath路径这样就能够根据相对路径引用到图片资源了,以下图所示

 

页面img引用图片

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

npm i html-withimg-loader -D
  1.  
    module.exports = {
  2.  
    module: {
  3.  
    rules: [
  4.  
    {
  5.  
    test: /\.(htm|html)$/,
  6.  
    use: 'html-withimg-loader'
  7.  
    }
  8.  
    ]
  9.  
    }
  10.  
    }

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

 

引用字体图片和svg图片

字体图标和svg图片均可以经过file-loader来解析

  1.  
    module.exports = {
  2.  
    module: {
  3.  
    rules: [
  4.  
    {
  5.  
    test: /\.(eot|ttf|woff|svg)$/,
  6.  
    use: 'file-loader'
  7.  
    }
  8.  
    ]
  9.  
    }
  10.  
    }

这样即便样式中引入了这类格式的图标或者图片都没有问题了,img若是也引用svg格式的话,配合上面写好的html-withimg-loader就都没有问题了

添加CSS3前缀

经过postcss中的autoprefixer能够实现将CSS3中的一些须要兼容写法的属性添加响应的前缀,这样省去咱们很多的时间

因为也是一个loader加载器,咱们也须要先安装一下

npm i postcss-loader autoprefixer -D

安装后,咱们还须要像webpack同样写一个config的配置文件,在项目根目录下建立一个postcss.config.js文件,配置以下:

  1.  
    module.exports = {
  2.  
    plugins: [require( 'autoprefixer')] // 引用该插件便可了
  3.  
    }

而后在webpack里配置postcss-loader

  1.  
    module.exports = {
  2.  
    module: {
  3.  
    rules: [
  4.  
    {
  5.  
    test: /\.css$/,
  6.  
    use: [ 'style-loader', 'css-loader', 'postcss-loader']
  7.  
    }
  8.  
    ]
  9.  
    }
  10.  
    }

转义ES6

在实际开发中,咱们在大量的使用着ES6及以后的api去写代码,这样会提升咱们写代码的速度,不过因为低版本浏览器的存在,不得不须要转换成兼容的代码,因而就有了经常使用的Babel了

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

那么再也不多说,既然要使用它,就先来安一下

npm i babel-core babel-loader babel-preset-env babel-preset-stage-0 -D

当把这些都安好后,咱们就开始配置,因为要兼容的代码不只仅包含ES6还有以后的版本和那些仅仅是草案的内容,因此咱们能够经过一个.babelrc文件来配置一下,对这些版本的支持

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

咱们再在webpack里配置一下babel-loader既能够作到代码转成ES5了

  1.  
    module.exports = {
  2.  
    module: {
  3.  
    rules: [
  4.  
    {
  5.  
    test:/\.js$/,
  6.  
    use: 'bable-loader',
  7.  
    include: /src/, // 只转化src目录下的js
  8.  
    exclude: /node_modules/ // 排除掉node_modules,优化打包速度
  9.  
    }
  10.  
    ]
  11.  
    }
  12.  
    }

在咱们每次npm run build的时候都会在dist目录下建立不少打好的包,若是积累过多可能也会混乱

因此应该在每次打包以前将dist目录下的文件都清空,而后再把打好包的文件放进去

这里提供一个clean-webpack-plugin插件

npm i clean-webpack-plugin -D
  1.  
    let CleanWebpackPlugin = require('clean-webpack-plugin');
  2.  
     
  3.  
    module.exports = {
  4.  
    plugins: [
  5.  
    // 打包前先清空
  6.  
    new CleanWebpackPlugin( 'dist')
  7.  
    ]
  8.  
    }

启动静态服务器

启动一个静态服务器,默认会自动刷新,就是说你对html,css,js文件作了修改并保存后,浏览器会默认刷新一次展示修改后的效果

正常状况下咱们都是在开发环境中开发项目,因此以前配置的脚本"dev"能够派上用场了,在执行npm run dev命令后,会启动静态服务器,咱们访问localhost:3000端口就能够看到开发的页面内容了

若是devServer里open设为true后,会自动打开浏览器

  1.  
    module.exports = {
  2.  
    devServer: {
  3.  
    contentBase: './dist',
  4.  
    host: 'localhost', // 默认是localhost
  5.  
    port: 3000, // 端口
  6.  
    open: true, // 自动打开浏览器
  7.  
    hot: true // 开启热更新
  8.  
    }
  9.  
    }

固然在npm run dev命令下,打包的文件存在于内存中,并不会产生在dist目录下

热更新和自动刷新的区别

在配置devServer的时候,若是hot为true,就表明开启了热更新

But这并没那么简单,由于热更新还须要配置一个webpack自带的插件而且还要在主要js文件里检查是否有module.hot

下面就让咱们直接看下代码是如何实现的

  1.  
    // webpack.config.js
  2.  
    let webpack = require('webpack');
  3.  
     
  4.  
    module.exports = {
  5.  
    plugins: [
  6.  
    // 热替换,热替换不是刷新
  7.  
    new webpack.HotModuleReplacementPlugin()
  8.  
    ],
  9.  
    devServer: {
  10.  
    contentBase: './dist',
  11.  
    hot: true,
  12.  
    port: 3000
  13.  
    }
  14.  
    }
  15.  
     
  16.  
    // 此时还没完虽然配置了插件和开启了热更新,但实际上并不会生效
  17.  
     
  18.  
    // index.js
  19.  
    let a = 'hello world';
  20.  
    document.body.innerHTML = a;
  21.  
    console.log( '这是webpack打包的入口文件');
  22.  
     
  23.  
    // 还须要在主要的js文件里写入下面这段代码
  24.  
    if (module.hot) {
  25.  
    // 实现热更新
  26.  
    module.hot.accept();
  27.  
    }

以上index.js中的内容,若是将变量a的值进行修改保存后,会在不刷新页面的状况下直接修改掉,这样就实现了热更新

那么热更新从如今看来和自动刷新浏览器的区别也不是太大嘛!自动刷新也是能够接受的啊

其实否则,热更新的好处可能在vue或者react中有更大的发挥,其中某一个组件被修改的时候就会针对这个组件进行热更新了,这里用到vue或react的同窗去实际体验一下吧

resolve解析

在webpack的配置中,resolve咱们经常使用来配置别名和省略后缀名

  1.  
    module.exports = {
  2.  
    resolve: {
  3.  
    // 别名
  4.  
    alias: {
  5.  
    $: './src/jquery.js'
  6.  
    },
  7.  
    // 省略后缀
  8.  
    extensions: [ '.js', '.json', '.css']
  9.  
    },
  10.  
    }

这个配置在webpack中比较简单,咱们也就再也不叙述了,下面来看点干货

提取公共代码

在webpack4以前,提取公共代码都是经过一个叫CommonsChunkPlugin的插件来办到的。到了4之后,内置了一个如出一辙的功能,并且起了一个好听的名字叫“优化”

下面咱们就来看看如何提取公共代码

  1.  
    // 假设a.js和b.js都同时引入了jquery.js和一个写好的utils.js
  2.  
    // a.js和b.js
  3.  
    import $ from 'jquery';
  4.  
    import {sum} from 'utils';

那么他们两个js中其中公共部分的代码就是jquery和utils里的代码了

能够针对第三方插件和写好的公共文件

  1.  
    module.exports = {
  2.  
    entry: {
  3.  
    a: './src/a.js',
  4.  
    b: './src/b.js'
  5.  
    },
  6.  
    output: {
  7.  
    filename: '[name].js',
  8.  
    path: path.resolve( 'dust')
  9.  
    },
  10.  
    // 提取公共代码
  11.  
    + optimization: {
  12.  
    splitChunks: {
  13.  
    cacheGroups: {
  14.  
    vendor: { // 抽离第三方插件
  15.  
    test: /node_modules/, // 指定是node_modules下的第三方包
  16.  
    chunks: 'initial',
  17.  
    name: 'vendor', // 打包后的文件名,任意命名
  18.  
    // 设置优先级,防止和自定义的公共代码提取时被覆盖,不进行打包
  19.  
    priority: 10
  20.  
    },
  21.  
    utils: { // 抽离本身写的公共代码,utils这个名字能够随意起
  22.  
    chunks: 'initial',
  23.  
    name: 'utils', // 任意命名
  24.  
    minSize: 0 // 只要超出0字节就生成一个新包
  25.  
    }
  26.  
    }
  27.  
    }
  28.  
    + },
  29.  
    plugins: [
  30.  
    new HtmlWebpackPlugin({
  31.  
    filename: 'a.html',
  32.  
    template: './src/index.html', // 以index.html为模板
  33.  
    + chunks: [ 'vendor', 'a']
  34.  
    }),
  35.  
    new HtmlWebpackPlugin({
  36.  
    filename: 'b.html',
  37.  
    template: './src/index.html', // 以index.html为模板
  38.  
    + chunks: [ 'vendor', 'b']
  39.  
    })
  40.  
    ]
  41.  
    }

经过以上配置,能够把引入到a.js和b.js中的这部分公共代码提取出来,以下图所示

 

指定webpack配置文件

在package.json的脚步里,咱们能够配置调用不一样的webpack配置文件进行打包,举个栗子

 

这样的好处在于能够针对不一样的需求进行一个特定的打包配置

 

就到这里吧

关于webpack4的一些常规操做就说到这里了,其实在工做当中更多时候,也并不须要咱们去配置这些内容

相关文章
相关标签/搜索