Webpack的浅入浅出

706 阅读7分钟

写在前面:这部分内容是根据coderwhy——王红元老师的课程所做的知识提炼;如果想要更好的学习,王红元老师的课程推荐给大家,讲的超级超级棒

Webpack的安装

  1. 首先需要安装node环境,可以参考以下两篇文章

  2. webpack的安装

​ 全局安装

npm install webpack@3.6.0 -g

//-g 全局安装

一般我们用的更多的是本地的,因为本地的才是真正和我们项目同步的

开发时依赖:只在开发阶段才发挥作用

npm install webpack@3.6.0 --save-dev

本地安装后,会生成node_modules文件夹和package.json;

package.json文件中

    "dependencies": {},     //运行时依赖
    "devDependencies": {    //开发时依赖
        "webpack": "^3.6.0"
    }

在终端敲的命令,执行的都是全局的

Webpack的初步使用

打开vscode的终端ctrl + 点 ,进入到项目文件目录下,在这里我的目录是

webpack01.png 执行命令,进行初步的打包

webpack ./src/main.js ./dist/bundle.js

表示 将main.js 这个入口文件打包到bundle.js这个出口文件当中

最后生成文件目录

webpack02.png

webpack的配置相关

定义入口文件与出口文件

首先,对项目进行npm初始化,在文件目录下执行npm init

Press ^C at any time to quit.
package name: (02webpack的配置) meetwebpack      //设置名称
version: (1.0.0)
description:
entry point: (webpack.config.js) index.html   //这个入口文件目前写什么都可以  然后就一直回车就可以了
test command:
git repository:
keywords:
author:
license: (ISC)
About to write to E:\VScode\xiangmu\webpack的使用\02webpack的配置\package.json:

{
  "name": "meetwebpack",
  "version": "1.0.0",
  "description": "",
  "main": "index.html",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}


Is this OK? (yes)

完成之后,在目录里生成了package.json文件,这个文件告诉我们当前项目的一些信息,包括项目名称,版本号,描述、脚本、作者、协议( "license": "ISC") ,如果是开源的话,需要这个协议,不开源的话就不需要。

之后,下载以下相关的依赖,在文件目录下执行npm install

之后,在项目目录下新建一个 webpack.config.js文件;文件名最好设置成这个,如果改的话,还需要进行配置才能正常运行。

webpack03.png

webpack.config.js文件中进行以下配置

const path = require('path') //依赖的node的包,所以要建立package.json

module.exports = {
    entry: './src/main.js', //导出 入口
    output: {
        //__dirname是node里面的一个全局变量,保存了当前文件所在的绝对路径
        //resolve函数用于两个路径的拼接
        path: path.resolve(__dirname, 'dist'), // 采用动态获取文件路径
        filename: 'bundle.js'
    }, //导出 出口  一般要求我们写成对象形式,path要写成绝对路径
}

之后,在进行打包的时候,就可以直接执行 webpack 命令

映射npm run 系列命令

在package.json文件中进行配置,原理我们在执行npm run 命令名字的时候,会找到package.json文件中的脚本信息srcipt当中,执行该命令名字对应的语句

{
    "name": "meetwebpack",
    "version": "1.0.0",
    "description": "",
    "main": "index.html",
    "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1",
        "build": "webpack"      //新增的内容
    },
    "author": "",
    "license": "ISC"
}

实质上相当于,把终端的 npm run build 命令 ,替换成scripts语句中对应引号中的内容(这里是webpack)进行执行,与直接在终端执行webpack命令不同的是,写在script脚本中的,会优先从本地找命令,而不是全局

package.json中的scripts的脚本在执行时,会按照一定的顺序寻找命令对应的位置。首先会寻找本地的node_modules/bin路径中对应的命令。如果没有找到,会去全局的环境变量里面找。

Webpack中的loader配置

loader时Webpack中的一个比较核心的概念,可以将需要加载的css、图片、也包括一些高级的ES6转成ES5代码等等。所以需要给webpack扩展对应的loader,不同的loader处理不同的文件

使用过程:

  1. 需要通过npm安装使用的loader

  2. 在webpack.config.js中的modules关键字下进行配置

    中文网址:www.webpackjs.com/

    loader:www.webpackjs.com/loaders

以css为例

npm install style-loader --save-dev

npm install --save-dev css-loader

从官网上找到 并执行,之后再 webpack.config.js文件配置

module: {
  rules: [{
    test: /\.css$/,   //匹配CSS文件
    //'css-loader'只负责加载,不负责解析
    //还需要'style-loader',负责把样式添加到DOM中
    //使用多个loader时,是从右向左读,因此'style-loader'放在前面
    use: ['style-loader','css-loader']
  }]
}

问题

配置完成之后,出现了npm run build错误--Unhandled promise rejections are deprecated. In the future, promise rejections,应该是版本不兼容的问题

可以参考以下版本

npm install css-loader@2.0.2 --save-dev

npm install style-loader@0.23.1 --save-dev

npm install --save-dev less-loader@4.1.0 less@3.9.0

npm install --save-dev url-loader@1.1.2

npm install --save-dev file-loader@3.0.1

npm install --save-dev babel-loader@7.1.5 babel-core@6.26.3 babel-preset-es2015@6.24.1

npm install vue@2.5.21 --save

npm install --save-dev vue-loader vue-template-compiler 

对图片文件进行处理时,用到url-loader、file-loader,两个当中其实用一个就可以了,要不然可能会出现图片加载不出来的情况。

在进行打包的过程中,webpack自动帮我们生成一个32为hash值,目的是为例防止命名重复,但是,真实的开发中,我们可能对打包的图片名字有一定的要求,比如,将所有的图片防止一个文件中,跟上图片原来的名字,同时防止重复

所以可以在options中添加一些选项

img :文件要打包到的文件夹

name : 获取图片原来的名字,放在该位置

hash:8:为了防止图片名称冲突,依然使用hash,但是我们只保留8位

ext:使用图片原来的扩展名

但是,我们发现图片并没有显示出来,这是因为图片使用的路径不正确 默认情况下 , webpack会将生成的路径直接返回给使用者 但是,我们整个程序是打包在dist文件夹下的,所以这里我们需要在路径下再添加一个dist/

Webpack中Vue的配置

回顾:

安装vue的三种方式:1. 直接下载引用到文件中;2. CDN引入;3.npm安装

在这里我们使用第三种方式,通过npm安装,vue就会被安装到项目中node_modules文件中,就可以把vue作为一个模块儿。

npm install vue --save

直接这样,在页面中是没有效果的。因为

Vue有两个版本:

  1. runtime-only 代码中,不可以有任何的template,只有运行时的代码,关于如何编译,无法起作用
  2. runtime-compiler 代码中,可以有template,因为compiler可以用于编译template

需要进行配置,告诉它我们要用第二个版本 ,在 webpack.config.js文件中进行配置

resolve: {
  //alias别名的意思
  alias: {
    'vue$': 'vue/dist/vue.esm.js'   //指定路径名
  }
}

若引入以vue为后缀名的文件,还需要 这两个版本一定要一致

npm install --save-dev vue-loader@15.4.2 vue-template-compiler@2.5.21 

Vue 加载器 v15 现在需要附带的 Webpack 插件才能正常工作:

// webpack.config.js
const VueLoaderPlugin = require('vue-loader/lib/plugin')

module.exports = {
  // ...
  plugins: [
    new VueLoaderPlugin()
  ]
}

入口文件引入时,要加后缀

import App from './vue/App.vue'

Webpack中的plugin

webpack04.png

添加版权声明的plugin

webpack.config.js文件中进行配置

// webpack.config.js
const webpack = require('webpack')

module.exports = {
  // ...
  plugins: [
    new webpack.BannerPlugin('这是我的版权声明')
  ]
}

打包html的plugin

可以自动生成一个index.html文件(可以指定模板来生成)

将打包的js文件,自动通过script标签插入到body中

安装:

npm install html-webpack-plugin@3.2.0 --save-dev

配置:

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

module.exports = {
  // ...
  plugins: [
       new HtmlWebpackPlugin()
  ]
}

可能出现的错误:

webpack05.png 下载完html-webpack-plugin后进行相应配置,结果突然报错

原因是因为下载了最新的版本太高的问题,在package.json中查询所下载的html-webpack-plugin的版本,将其改成3.2.0的版本,然后在终端重新npm install 一下就好了

完成之后,可能还需要:

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

module.exports = {
  // publicPath: 'dist/'    //把公共路径去掉
  // ...
  plugins: [
       new HtmlWebpackPlugin({
         template:'index.html'   //用于显示vue模板
       })
  ]
}

对js压缩(丑化)的plugin

对打包的js文件进行压缩,去除掉多余的空格、将变量用简单的符号代替,添加插件,若使用CLI2,为保持一致,版本号需要指定1.1.1

在开发阶段,我们一般不需要使用压缩,不方便修改代码

安装:

npm install uglifyjs-webpack-plugin@1.1.1 --save-dev

配置:

// webpack.config.js
const UglifyjsWebpackPlugin = require('uglifyjs-webpack-plugin')

module.exports = {
  // publicPath: 'dist/'    //把公共路径去掉
  // ...
  plugins: [
      new UglifyjsWebpackPlugin()
  ]
}

Webpack搭建本地服务器

webpack提供了一个可选的本地开发服务器,这个本地服务器基于nodejs搭建,内部使用express框架,可以实现我们想要让浏览器自动刷新显示我们修改后的结果。

在最终编译阶段,这个配置就不需要了,可以根据项目的哥哥阶段,修改响应的配置

安装:

npm install webpack-dev-server@2.9.3 --save-dev

devserver也是作为webpack中的一个选项,选项本身可以设置如下属性︰

contentBase:为哪一个文件夹提供本地服务,默认是根文件夹,我们这里要填写./dist

port:端口号

inline :页面实时刷新

historyApiFallback :在SPA(单页面复叶面)页面中,依赖HTML5的history模式

webpack.config.js文件配置修改如下:

// webpack.config.js

module.exports = {
  // ...
  devServer: {
        contentBase: './dist',
        inline: true
    }
}

我们可以再配置另外—个scripts :--open参数表示直接打开浏览器

"dev": "webpack-dev-server --open"

执行:

npm run dev

终止批处理操作

ctrl + c 快捷键

Webpack配置文件的分离

对webpack中的配置文件进行抽离,将开发阶段和运行阶段响应的配置相分离

在i昂木中建立相关的配置文件夹build

里面新建3个文件:

公共的配置放在base.config.js中

开发时特殊的配置放在dev.config.js中

生产时特殊的配置放在prod.config.js中

安装:

npm install webpack-merge@4.1.5 --save-dev

dev.config.js中

//开发时特殊的配置放在dev.config.js中
const WebpackMerge = require('webpack-merge')
const baseConfig = require('./base.config')

module.exports = WebpackMerge(baseConfig, {
    devServer: {
        contentBase: './dist',
        inline: true
    }
})

prod.config.js中:

//生产时特殊的配置放在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()
    ]
})

对文件生成的路径重新配置

// webpack.config.js

module.exports = {
  path: path.resolve(__dirname, '../dist'), // 采用动态获取文件路径
}

对package.json进行修改

{
    //....
    "scripts": {
        "build": "webpack --config ./build/prod.config.js",   //指定配置文件路径
        "dev": "webpack-dev-server --config ./build/dev.config.js"
    },
	//.....
}

webpack.config.js文件可以删掉啦!

vue-cli.png

vue-cli02.png

关于文件别名的配置

webpack里面某些内容,可以帮我们解决文件当中的路径问题,其中很重要的就是别名

若使用cli2,直接找到配置文件进行修改

若使用cli3以上,则需要在根目录建立一个配置文件

vue.config.js

const path = require('path');//引入path模块,为配置别名做准备
function resolve(dir){   
	return path.join(__dirname,dir)//path.join(__dirname)设置绝对路径
}

module.exports = {    
	chainWebpack: (config) => {        
			config.resolve.alias        		
			.set('@',resolve('./src'))        		
			.set('components',resolve('./src/components')) //set第一个参数:设置的别名,第二个参数:设置的路径 
      .set('assets',resolve('./src/assets'))   
		}
	}

注意:若不是import引入的,前面需要加~

修改配置文件要重启