Vue.js- webpack 详解

1.1 什么是Webpack?

从本质上来讲,webpack是一个现代的JavaScript应用的静态模块打包工具。

前端模块化

  • 在ES6之前,我们要想进行模块化开发,就必须借助于其他的工具,让我们可以进行模块化开发。
  • 并且在通过模块化开发完成了项目后,还需要处理模块间的各种依赖,并且将其进行整合打包。
  • 而webpack其中一个核心就是让我们可能进行模块化开发,并且会帮助我们处理模块间的依赖关系。
  • 而且不仅仅是JavaScript文件,CSS、图片、json文件等等在webpack中都可以被当做模块来使用。

打包

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

webpack安装

安装webpack首先需要安装Node.js,Node.js自带了软件包管理工具npm。NPM官方的管理的包都是从 http://npmjs.com下载的,但是这个网站在国内速度很慢。这里推荐使用淘宝 NPM 镜像 http://npm.taobao.org/ ,淘宝 NPM 镜像是一个完整npmjs.com 镜像,同步频率目前为 10分钟一次,以保证尽量与官方服务同步。

设置镜像和存储地址:

# 由于npm代码仓库的服务器在国外,由于Great Firewall的缘故,这时可以使用淘宝的npm代码仓库,通过npm安装cnpm
npm install -g cnpm --registry=https://registry.npm.taobao.org
# 安装成功后,可以通过以下命令查看cnpm版本:
cnpm -v
#设置npm下载包时保存在本地的地址(建议英文目录),通过cnpm来操作下载速度会得到很大提升,但包的版本不一定是最新的。
cnpm config set prefix "E:\\Develop\\repo_npm"
#查看cnpm配置信息
cnpm config list

查看自己的node版本

node -v

全局安装webpack(这里我先指定版本号3.6.0,因为vue cli2依赖该版本)

cnpm install webpack@3.6.0 -g

查看webpack版本

webpack --version

1.2 Webpack 初体验

项目目录

文件和文件夹解析:

  • dist文件夹:用于存放之后打包的文件。
  • src文件夹:用于存放我们写的源文件
    • main.js:项目的入口文件。具体内容查看下面详情。
    • mathUtils.js:定义了一些数学工具函数,可以在其他地方引用,并且使用。
  • index.html:浏览器打开展示的首页html,package.json:通过npm init生成的,npm包管理的文件。

mathUtils.js

function add(num1, num2) {
  return num1 + num2
}

function mul(num1, num2) {
  return num1 * num2
}

// 模块导出
module.exports = {
  add,
  mul
}

info.js

// 导出模块
export const name = 'GuardWhy';
export const age = 18;
export const height = 1.71

main.js

// 1. 使用commonjs的模块化导入
const {add, mul} = require('./mathUtils')

// 输出结果
console.log(add(20, 30));
console.log(mul(20, 30));

// 2.使用es6的模块化规范
import {name, age, height} from "./info";

console.log(name);
console.log(age);
console.log(height);

index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>webpack基本使用</title>
</head>
<body>
<!--引入js文件-->
<script src="dist/bundle.js"></script>
</body>
</html>

webpack的指令打包

webpack src/main.js dist/bundle.js

使用打包后的文件

打包后会在dist文件下,生成一个bundle.js文件
bundle.js文件,是webpack处理了项目直接文件依赖后生成的一个js文件,只需要将这个js文件在index.html中引入即可。

index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>webpack基本使用</title>
</head>
<body>
<!--引入js文件-->
<script src="dist/bundle.js"></script>
</body>
</html>

执行结果

1.3 webpack的配置

项目目录

配置文件

webpack.config.js

// 1.获得路径
const path = require('path');

// 支持导出
module.exports = {
  entry: './src/main.js',
  output: {
    path: path.resolve(__dirname,'dist'),
    filename:'bundle.js'
  },
}

局部安装webpack

因为一个项目往往依赖特定的webpack版本,全局的版本可能很这个项目的webpack版本不一致,导出打包出现问题。
所以通常一个项目,都有自己局部的webpack。

cnpm install webpack@3.6.0 --save-dev

配置package.json

打开项目的命令所在位置,执行npm init命令,可得到package.json文件,可以在package.json的scripts中定义自己的执行脚本

{
  "name": "guardwhy",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack"
  },
  "author": "guardwhy",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^3.6.0"
  },
  "dependencies": {},
  "description": ""
}

当执行npm run build命令时候会直接生成bundle.js

1.4 什么是loader?

webpack用来做什么呢?

在之前的实例中,主要是用webpack来处理写的js代码,并且webpack会自动处理js之间相关的依赖。
在开发中不仅仅有基本的js代码处理,也需要加载css、图片,也包括一些高级的将ES6转成ES5代码,将TypeScript转成ES5代码,将scss、less转成css,将.jsx、.vue文件转成js文件。对于webpack本身的能力来说,对于这些转化是不支持的。那怎么办呢?给webpack扩展对应的loader就可以啦。

loader使用过程

步骤一:通过npm安装需要使用的loader。
步骤二:在webpack.config.js中的modules关键字下进行配置。

1.4.1 css文件处理

项目开发过程中,必然需要添加很多的样式,而样式往往写到一个单独的文件中。
在src目录中,创建一个css文件,其中创建一个normal.css文件,也可以重新组织文件的目录结构,将零散的js文件放在一个js文件夹中。


normal.css中的代码非常简单,就是将body设置为red。

body {
    background-color: red;
}

但是,这个时候normal.css中的样式会生效吗?当然不会,因为压根就没有引用它。
webpack也不可能找到它,因为只有一个入口,webpack会从入口开始查找其他依赖的文件。

在入口文件中引用

main.js

// 1. 使用commonjs的模块化导入
const {add, mul} = require('./js/mathUtils')

// 输出结果
console.log(add(20, 30));
console.log(mul(20, 30));

// 2.使用es6的模块化规范
import {name, age, height} from "./js/info";

console.log(name);
console.log(age);
console.log(height);

// 依赖css文件
require('./css/normal.css')

执行 npm run build 命令后出现错误!!!

加载*.css文件和格式必须有对应的loader

文档目录: https://webpack.docschina.org/loaders/#styling

安装CSS-loader

cnpm install --save-dev css-loader@3.6.0

安装style-loader

cnpm install --save-dev style-loader@1.3.0

安装以后可以在package.json文件中查看到版本号。

配置webpack.config.js

// 1.获得路径
const path = require('path');

// 支持导出
module.exports = {
  entry: './src/main.js',
  output: {
    path: path.resolve(__dirname,'dist'),
    filename:'bundle.js',
    publicPath: 'dist/'
  },
  module: {
    rules: [
      { test: /\.css$/,
        /*
        css-loader只负责将css文件进行加载
        style-loader负责将样式添加到DOM中
        使用多个loader时, 是从右向左
        */
        use: ['style-loader','css-loader']
      }
    ]
  }
}

执行npm run build命令,可能会出现以下的问题。

通过查看错误提示,发现会不会有可能是css-loader的版本太高了,所以把css-loader的版本由4.2.0改为了3.6.0!!!

执行结果

1.4.2 less文件处理

项目目录

在入口文件中引用

main.js

// 1. 使用commonjs的模块化导入
const {add, mul} = require('./js/mathUtils')

// 输出结果
console.log(add(20, 30));
console.log(mul(20, 30));

// 2.使用es6的模块化规范
import {name, age, height} from "./js/info";

console.log(name);
console.log(age);
console.log(height);

// 依赖css文件
require('./css/normal.css')

// 依赖less文件
require('./css/special.less')
document.write('<h3>kobe是mvp!!!</h3>')

加载*.less文件和格式必须有对应的loader

文档目录: https://webpack.docschina.org/loaders/#styling

安装less-loader

cnpm install less-loader@5.0.0 --save-dev

安装less

cnpm install less@3.13.1--save-dev

安装以后可以在package.json文件中查看到版本号。

配置webpack.config.js

// 1.获得路径
const path = require('path');

// 支持导出
module.exports = {
  entry: './src/main.js',
  output: {
    path: path.resolve(__dirname,'dist'),
    filename:'bundle.js'
  },
  module: {
    rules: [
      { test: /\.css$/,
        /*
        css-loader只负责将css文件进行加载
        style-loader负责将样式添加到DOM中
        使用多个loader时, 是从右向左
        */
        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
        }]
      }
    ]
  }
}

执行npm run build命令。

执行结果

1.4.3 图片文件处理

项目目录

normal.css中的样式

body {
    background: url("../img/timg.jpg");
}

加载图片文件和格式必须有对应的loader

文档目录: https://webpack.docschina.org/loaders/#files

安装url-loader

cnpm install url-loader@2.0.0 --save-dev

安装file-loader

cnpm install file-loader@2.0.0 --save-dev

安装以后可以在package.json文件中查看到版本号。

配置webpack.config.js

// 1.获得路径
const path = require('path');

// 支持导出
module.exports = {
  entry: './src/main.js',
  output: {
    path: path.resolve(__dirname,'dist'),
    filename:'bundle.js',
    publicPath: 'dist/'
  },
  module: {
    rules: [
      { test: /\.css$/,
        /*
        css-loader只负责将css文件进行加载
        style-loader负责将样式添加到DOM中
        使用多个loader时, 是从右向左
        */
        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)$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              // 当加载的图片,小于limit时会将图片编译成base64字符串形式
              //当加载的图片,大于limit时需要使用file-loader模块进行加载
              limit: 13000,
              name: 'img/[name].[hash:8].[ext]'
            }
          }
        ]
      }
    ]
  }
}

执行npm run build命令。

执行结果

1.4.4 ES6语法处理

果希望将ES6的语法转成ES5,那么就需要使用babel,而在webpack中,直接使用babel对应的loader就可以了。

安装babel-loader

cnpm install --save-dev babel-loader@7 babel-core babel-preset-es2015

安装以后可以在package.json文件中查看到版本号。

配置webpack.config.js

// 1.获得路径
const path = require('path');

// 支持导出
module.exports = {
  entry: './src/main.js',
  output: {
    path: path.resolve(__dirname,'dist'),
    filename:'bundle.js',
    publicPath: 'dist/'
  },
  module: {
    rules: [
      { test: /\.css$/,
        /*
        css-loader只负责将css文件进行加载
        style-loader负责将样式添加到DOM中
        使用多个loader时, 是从右向左
        */
        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)$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 13000,
              name: 'img/[name].[hash:8].[ext]'
            }
          }
        ]
      },
      {
        test: /\.js$/,
        exclude: /(node_modules|bower_components)/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['es2015']
          }
        }
      }
    ]
  }
}

重新打包,查看bundle.js文件,发现其中的内容变成了ES5的语法

1.5 webpack配置Vue

1.5.1 引入vue.js

安装Vue,在实际项目中也会使用vue的,所以并不是开发时依赖。

cnpm install vue@2.5.11 --save

main.js

import Vue from 'vue'

new Vue({
    el:'#app',
    data:{
        message:'hello Vue.js!!!'
    }
})

index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>webpack配置Vue</title>
</head>
<body>

<div id = "app">
  {{message}}
</div>
<!--引入js文件-->
<script src="dist/bundle.js"></script>
</body>
</html>

执行npm run build 命令结果,报错!!!

解决方案修改webpack的配置

webpack.config.js

// 以下内容
resolve: {
    // alias: 别名
    extensions: ['.js', '.css', '.vue'],
    alias: {
      'vue$': 'vue/dist/vue.esm.js'
    }
  }

执行结果

1.5.2 el和template区别

正常运行之后,来考虑另外一个问题

如果希望将data中的数据显示在界面中,就必须是修改index.html
但是html模板在之后的开发中,并不希望手动的来频繁修改。

定义template属性

在前面的Vue实例中,我们定义了el属性,用于和index.html中的#app进行绑定,让Vue实例之后可以管理它其中的内容。
这里,可以将div元素中的{{message}}内容删掉,只保留一个基本的id为div的元素。

el和template模板的关系是什么呢?

知道el用于指定Vue要管理的DOM,可以帮助解析其中的指令、事件监听等。

而如果Vue实例中同时指定了template,那么template模板的内容会替换掉挂载的对应el的模板。

这样做之后就不需要在以后的开发中再次操作index.html,只需要在template中写入对应的标签即可。

代码示例

main.js

import Vue from 'vue'

new Vue({
    el:'#app',
    template:`
    <div>
        <h3>{{message}}</h3>
        <button @click= "btnClick">按钮</button>
        <h3>{{name}}</h3>
    </div>
    `,
    data:{
        message:'hello Vue.js!!!',
        name: 'guardwhy'
    },
    methods:{
        btnClick(){
            
        }
    }
})

index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>webpack配置Vue</title>
</head>
<body>

<div id = "app">
</div>
<!--引入js文件-->
<script src="dist/bundle.js"></script>
</body>
</html>

执行结果

1.5.3 Vue组件化开发

项目目录

安装vue-loader和vue-template-compiler

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

安装以后可以在package.json文件中查看到版本号。

修改webpack.config.js的配置文件

// 1.获得路径
const path = require('path');
// 引入webpack
const webpack = require('webpack');

// 支持导出
module.exports = {
  entry: './src/main.js',
  output: {
    path: path.resolve(__dirname,'dist'),
    filename:'bundle.js',
    publicPath: 'dist/'
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /(node_modules|bower_components)/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['es2015']
          }
        }
      },
      {
        test: /\.vue$/,
        use: ['vue-loader']
      }

    ]
  },
  resolve: {
    // alias: 别名
    extensions: ['.js', '.css', '.vue'],
    alias: {
      'vue$': 'vue/dist/vue.esm.js'
    }
  }
}

代码示例

main.js

import Vue from 'vue'
import App from "./vue/App.vue"

new Vue({
    el:'#app',
    template:'<App/>',
    components:{
        App
    }
})

App.vue

<template>
  <div>
    <h3 class="title">{{message}}</h3>
    <button @click="btnClick">按钮</button>
    <h3>{{name}}</h3>
    <Cpn></Cpn>
  </div>
</template>

<script>
  // 引入组件
  import Cpn from './Cpn'
  export default {
    name: "App",
    // 注册Cpn组件
    components: {
      Cpn
    },
    data(){
      return {
        message: 'hello webpack!!!!',
        name: 'guardwhy'
      }
    },
    methods: {
      btnClick(){

      }
    }
  }
</script>

<style scoped>
  .title {
    color: green;
  }
</style>

Cpn.vue

<template>
  <div>
    <h3>我是NBA球星</h3>
    <p>我是三分王,我是Curry</p>
    <h3>{{name}}</h3>
  </div>
</template>

<script>
export default {
  name: "Cpn",
  data(){
    return{
      name: 'hello Vue.js!!!'
    }
  }
}
</script>

<style scoped>

</style>

index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>webpack配置Vue</title>
</head>
<body>

<div id = "app">
</div>
<!--引入js文件-->
<script src="dist/bundle.js"></script>
</body>
</html>

执行命令npm run build,执行成功!!!

1.6 认识plugin

plugin是什么?

  • plugin是插件的意思,通常是用于对某个现有的架构进行扩展。
  • webpack中的插件,就是对webpack现有功能的各种扩展,比如打包优化,文件压缩等等。

loader和plugin区别

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

plugin的使用过程:

  • 步骤一:通过npm安装需要使用的plugins(某些webpack已经内置的插件不需要安装)。
  • 步骤二:在webpack.config.js中的plugins中配置插件。

1.6.1 打包html的plugin

HtmlWebpackPlugin插件具体作用

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

安装HtmlWebpackPlugin插件

cnpm install html-webpack-plugin --save-dev

安装以后可以在package.json文件中查看到版本号。

修改webpack.config.js文件

// 引入插件
const HtmlWebpackPlugin = require('html-webpack-plugin');

// 支持导出
module.exports = {
  entry: './src/main.js',
  output: {
    path: path.resolve(__dirname,'dist'),
    filename:'bundle.js',
    // publicPath: 'dist/'
  },
  plugins: [
    // 添加插件
    new HtmlWebpackPlugin({
      template: 'index.html'
    }),
  ]
}

index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>webpack配置Vue</title>
</head>
<body>

<div id = "app">
</div>
</body>
</html>

使用命令 npm run build 执行操作,发现报错!!!

解决方案!!!

HtmlWebpackPlugin插件版本太高了,将HtmlWebpackPlugin版本设置为2.0.0

终端执行命令

cnpm install

操作结果

1.6.2 js压缩的Plugin

安装uglifyjs-webpack-plugin插件

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

修改webpack.config.js文件

// 添加压缩js插件
const UglifyjsWebpackPlugin = require('uglifyjs-webpack-plugin');

// 支持导出
module.exports = {
  entry: './src/main.js',
  output: {
    path: path.resolve(__dirname,'dist'),
    filename:'bundle.js',
    // publicPath: 'dist/'
  },
  plugins: [
    new UglifyjsWebpackPlugin()
  ]
}
posted @ 2021-10-28 19:56  guardwhy  阅读(414)  评论(0编辑  收藏  举报