Webpack

2020-09-29  本文已影响0人  想吃热干面了

一、什么是webpack

官方解释

从本质上来讲,webpack是一个现代的JavaScript应用的静态模块打包工具
上述解释,核心就是 模块 和 打包。

前端模块化:webpack中模块化的概念

在学习模块化时,我们了解了一些

目前使用的前端模块化的方案:AMD、CMD、CommonJS、ES6。但是除了ES6浏览器有支持可以直接使用外,其他的必须借助于其他工具,支持我们进行模块化开发,并且通过模块化开发完成了项目,还需要处理模块间的各种依赖,将其进行整合打包。
webpack其中一个核心就是让我们可以进行模块化开发,并且帮助我们处理模块间的依赖关系。
这就是webpack中模块化的概念。
注:webpack中js、css、图片、json文件都可以当作模块使用。

打包如何理解

就是将webpack中的各种资源模块化进行打包合并成一个或多个包(Bundle)。
在打包的过程中,还可以对资源进行处理,比如压缩图片,将scss转成css,ES6语法转成ES5语法,将TypeScript转成JavaScript等等操作

webpack打包与grunt/gulp的区别

grunt/gulp

grunt/gulp的核心是Task:通过配置一系列的Task,定义task要处理的事务(ES6、ts转化;图片压缩等),之后依次执行这些task,让整个流程自动化。所以grunt/gulp也被称为前端自动化任务管理工具。

grunt/gulp适用于工程模块依赖非常简单(甚至没有用到模块化的概念)的只需进行简单的合并、压缩的场合。

webpack与grunt/gulp的不同

二、webpack安装

webpack的正常运行是依赖于node环境的。node环境依赖各种包,npm是node管理包的工具。

三、webpack的基本使用

1.项目结构:

创建项目时,有两个文件夹,一个是dist文件夹,是打包,发布使用的。一个是src文件夹,主要编码开发用。

2.js文件的打包

3.webpack.config.js和package.json的配置

配置webpack.config.js可以简化打包命令
const path = require('path')
module.exports = {
  mode : 'development',
  entry: './src/main.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js'
  },
}
package.json
{
  "name": "meetwebpack",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^3.6.0"
  }
}
本地安装webpack
npm install webpack@3.6.0 --save-dev
在配置完成后,我们可以在终端中执行“webpack”命令就可以打包了。需要注意的是,在终端中执行webpack命令,执行的都是全局安装的webpack。所以可以在package.json中配置脚本,使得优先寻找本地的webpack。
"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack"
  },
配置后,执行下面命令就可以打包了
  npm run build

四、loader

loader是webpack中一个非常核心的概念

当我们需要在webpack中加载css、图片,高阶ES6转成ES5代码,TypeScript转成ES5代码,将scss、less转成css,将.jsx、.vue文件转成js文件等等时,就需要给webpack扩展对应的loader。
loader使用过程:

1.css文件打包

2.less文件的处理

3.图片文件处理

limit参数:大小限制
当加载的图片,小于limit时,会将图片编译成base64字符串形式
当加载的图片,大于limit时,需要使用file-loader模块进行加载 且当成模块 需要打包
安装file-loader,file-loader不需要配置,安装即可
  npm install file-loader@1.1.11 --save-dev
name参数:图片打包后默认名字是一串hash值,并且是在dist文件夹下,不利于管理查看。这时我们可以使用name属性,对其重新命名,并且放到统一的文件夹中管理。
 name: 'img/[name].[hash:8].[ext]'
 img文件夹;[name]表示原来的名字;(.)用来拼接;[hash:8]表示生成8位hash值;[ext]表示图片格式。

4.ES6语法处理

目前,有一些浏览器对一些ES6语法还不支持,所以打包js文件时可能需要将ES6语法转成ES5。

presets对应一个文件,没有这个文件时,就先使用es2015

五、webpack配置vue

1.安装vue.js(需要将vue当作一个模块,所以通过npm安装)

  npm install vue@2.5.21 --save

2.引入依赖

  import Vue from 'vue'

3.简单尝试

<div id="app">
  <h2>{{message}}</h2>
</div>

import Vue from 'vue';

const app = new Vue({
  el: '#app',
  data: {
    message: 'Hello webpack'
  }
});

4.但是打包运行后会报错

webpack-vue.png

原因:我们只是安装了runtime-only,不允许有template,代码中div会被当作一个template


vue.png

5.解决方法:在webpack.config.js中添加配置,改变指定的vue文件

  resolve: {
    //alias:别名
    alias: {
      'vue$': 'vue/dist/vue.esm.js'
    }
  }

6.el和template的区别

真实项目中,我们为了不频繁更改index.html的代码的,所以vue显示的内容可以写在vue实例中的template属性。
  new Vue({
    el: '#app',
    template: `
    <div>
    <h2>{{message}}</h2>
    <button @click="btnClick"></button>
    <h2>{{name}}</h2>
    </div> 
    `,
  data: {
      message: 'Hello webpack',
      name: 'codeWhy'
  },
  methods: {
    btnClick() {

    }
  }
});

在运行后,template属性的内容会替换掉index.html中id为app的div

7.vue的终极使用方案(vue文件封装处理)

vue模版 (2).png

六、认识plugin

plugin是什么:

plugin是插件的意思,通畅用于对某个现有的架构进行扩展

loader和plugin的区别:

loader主要用于转换某些类型的模块,是一个转换器。
plugin是插件,对webpack本身的扩展,是一个扩展器。

使用过程:

1).通过npm安装
2).在webpack.config.js中的plugins中配置

各种plugin

①添加版权的plugin
作用:打包后的文件上方标识代码版权所有者
  const webpack = require('webpack');

  module.exports = {
    plugins: [
        new webpack.BannerPlugin('最终版权归国家所有')
    ]
  }
②打包html的plugin

目前,我们的index.html文件是放在根目录下的。在我们真是发布项目时的dist文件夹中并没有index.html。所以我们需要将index.html打包到dist文件夹中。这时就可以使用HtmlWebpackPlugin插件。

作用:

自动生成一个index.html文件(可以指定模版)
将打包的js文件自动通过script标签插入到body中

安装HtmlWebpackPlugin插件
  npm install html-webpack-plugin@3.2.0 --save-dev
配置
    plugins: [
        new HtmlWebpackPlugin({
          template: 'index.html'
        }),
    ]

③js压缩的plugin

作用:将打包的js压缩
安装uglifyjs-webpack-plugin插件
        npm install uglifyjs-webpack-plugin@1.1.1 --save-dev
配置:开发时不需要,不好调试
    plugins: [
        new UglifyjsWebpackPlugin(),
    ]

七、webpack-dev-server搭建本地服务器(打包时不需要)

存在问题:
在开发中,我们不可能每修改次代码就从新打包来看修改后的结果,这样从磁盘中读取信息影响效率。
解决方法:
 webpack提供了一个可选的本地开发服务器,基于node.js搭建,内部是express框架,使浏览器可以自动刷新显示我们修改后结果。从而使得我们可以在确认无误后只打一次包。
它是一个单独的模块,使用前也需要安装
  npm install --save-dev webpack-dev-server@2.9.1
配置webpack.config.js
module.exports = {
    devServer: {        
      contentBase: './dist',(为那一个文件夹提供本地服务,默认根文件,我们需填上打包指定文件夹)
      inline: true,(页面实时刷新)
      port(可以指定端口号,默认8080)          
    }
}
还需在package.json文件中配置启动脚本
     "dev": "webpack-dev-server"
配置后在终端中使用下面的命令即可开启服务
     npm run dev
补充:

配置脚本还可以写成("dev": "webpack-dev-server --open"),添加--open后缀,意思是可以在启动服务时,自动打开网页。

八、配置文件的分离

在webpack.config.js配置文件中,有些是开发时的配置(webpack-dev-server),有的是编译时的配置(uglifyjs-webpack-plugin)。如果都放在一起的话不利于管理。所以我们接下来可以将配置文件进行分离操作。

需要安装webpack-merge:可以对配置文件进行合并
  npm install webpack-merge@4.1.5 --save-dev
要达成下图中的效果:将一个文件分成三个文件
配置分离.png
原文件:webpack.config.js
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const UglifyjsWebpackPlugin = require('uglifyjs-webpack-plugin');

module.exports = {
  entry: './src/main.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js',
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [ 'style-loader', 'css-loader' ]
      },
  {
    test: /\.less$/,
    use: [{
      loader: "style-loader" // creates style nodes from JS strings
    }, {
      loader: "css-loader" // translates CSS into CommonJS
    }, {
      loader: "less-loader" // compiles Less to CSS
    }]
  },
  {
    test: /\.(png|jpg|gif|jpeg)$/,
    use: [
      {
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: 'img/[name].[hash:8].[ext]'
        }
      }
    ]
  },
  {
    test: /\.vue$/,
    use: ['vue-loader']
  }
]
  },
  resolve: {
    alias: {
      'vue$': 'vue/dist/vue.esm.js'
    }
  },
  plugins: [
      new webpack.BannerPlugin('最终版权归国家所有'),
      new HtmlWebpackPlugin({
        template: 'index.html'
      }),
      new UglifyjsWebpackPlugin(),
  ],
  devServer: {
    contentBase: './dist',
    inline: true
  }
}
将开发时需要的配置抽出:使用webpackMerge可以和公共的配置合并 dev.config.js
const webpackMerge = require('webpack-merge');
const baseConfig = require('./base.config');

module.exports = webpackMerge(baseConfig, {
  devServer: {
    contentBase: './dist',
    inline: true
  }
})
将打包时需要的配置抽出:使用webpackMerge可以和公共的配置合并 prod.config.js
const UglifyjsWebpackPlugin = require('uglifyjs-webpack-plugin');
const webpackMerge = require('webpack-merge');
const baseConfig = require('./base.config');

module.exports = webpackMerge(baseConfig, {
  plugins: [
    new UglifyjsWebpackPlugin(),
  ],
})
整理公共配置:base.config.js
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const UglifyjsWebpackPlugin = require('uglifyjs-webpack-plugin');

module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, '../dist'),
filename: 'bundle.js',
},
module: {
rules: [
  {
    test: /\.css$/,
    use: [ 'style-loader', 'css-loader' ]
  },
  {
    test: /\.less$/,
    use: [{
      loader: "style-loader" // creates style nodes from JS strings
    }, {
      loader: "css-loader" // translates CSS into CommonJS
    }, {
      loader: "less-loader" // compiles Less to CSS
    }]
  },
  {
    test: /\.(png|jpg|gif|jpeg)$/,
    use: [
      {
        loader: 'url-loader',
        options: {
              limit: 10000,
              name: 'img/[name].[hash:8].[ext]'
            }
          }
         ]
      },
      {
        test: /\.vue$/,
      use: ['vue-loader']
      }
    ]
  },
  resolve: {
    //alias:别名
    alias: {
      'vue$': 'vue/dist/vue.esm.js'
    }
  },
  plugins: [
    new webpack.BannerPlugin('最终版权归国家所有'),
    new HtmlWebpackPlugin({
      template: 'index.html'
    }),
  ],
}
上一篇 下一篇

猜你喜欢

热点阅读