使用 webpack 搭建 vue 开发环境

本篇笔记为学习网易公开课后做的笔记,课程是网易谭金龙老师讲的, 地址:https://study.163.com/sl/VsaN

请勿直接爬走,本文地址:https://www.cnblogs.com/xiaoxuStudy/p/13492608.html

本篇笔记的内容不一定完全正确,因为我有的地方不懂,先把笔记做下来, 如果有错误的地方麻烦指出,谢谢。 

 

目录:

1. vue-cli 的工作原理

2. 用 webpack 搭建 vue 项目

 

一. vue-cli 的工作原理

   如果为了“开箱即用”,可以使用命令 vue create project 或 vue init webpack project 去创建 vue 项目, “开箱即用”是约定大于配置,简单来说就是能不配置就不配置按照人家的方式来,作者不建议配置但是不会拦着我们去配置。但是如果想要成为一个高级前端工程师或架构师,最好要理解 vue-cli 的架构原理。

  脚手架:主体结构全部搭建好了,我们可以在利用这个主体结构去完成我们的需求

  vue-cli 不是一个单独的东西,甚至它不是一个东西,它自己也没有什么特别的功能,它其实是 git 上的一个项目,或者说它就是一堆文件,真正有功能的是 webpack。可以到 github 上看看,搜索 webpack, 点击下图这个进去看看

 点 template 进去看看

  下图这个目录就是使用命令 vue init webpack xxx 时下载的东西,使用的时候用命令 npm run start 去启动这些东西

  但是,现在使用的基本上都是 vue-cli3.x 或者 vue-cli4.x,vue-cli3.x 是基于 webpack4 打造的,vue-cli2.x 是基于 webpack3 打造的,webpack3 跟 webpack4 的区别挺大的,所以不建议全局安装 webpack,因为如果不同的项目是基于不同的 webpack 但是又全局安装了 webpack,这样子就可能会出问题。

  vue-cli3 学习了 rollup 的零配置思路,所以在项目初始化之后没有以前的一些东西了,也找不到配置文件了,这帮助开发者解决了绝大部分情形下的 webpack 配置,但是,我们还是很有必要去了解 webpack 的。

  vue-cli 这个脚手架其实什么都没干,其实,vue-cli 就是一个下载器,官方叫 vue-cli 启动器,它的作用是帮助我们快速去建立一些基本项目,但是这个项目不是完全空白的,有些基本的东西,比如说可以根据选择的项目的不同下载不同的依赖、根据我们的选择更改项目名、可以选择单元测试方法是单元测试还是一对一测试。

  接着上面看 github 的东西,打开 package.json 看看

  可以看到 package.json 里面有各种各样的 loader,webpack 只能处理 js 文件,webpack 不认识 vue,loader 的作用就是把 vue 文件转成 js 文件,之后配置上 plugin 各种扩展功能。总结一下,webpack 中的 loader 是为了将 webpack 不认识的文件转成 js 文件。各种 loader、plugin 为 webpack扩展功能,所以 vue-cli 没有这么了不起,真正牛逼的是 webpack。vye

  了解 vue-cli 工作原理之后,可以利用 webpack 自己去搭建一个 vue 的开发环境。总而言之,vue-cli 是一个下载器,它从 git 上去下载一个目录。

 

. 用 webpack 搭建 vue 项目

下面利用 webpack 去搭建去架构一个 vue 的开发环境,甚至可以说是自己去架构一个 vue-cli。

 例子  

首先新建一个文件夹,我新建了个 0812 文件夹,到该目录下生成一个 package.json 工程管理文件

命令:  yarn init -y  

 

因为要利用 webpack 去搭建去架构一个 vue 的开发环境,所以要把 webpack 拿下来。不建议全局安装 webpack。其中 webpack-cli 是一个简易客户端,用于与 webpack 协议连接,在 webpack3 里它本身和客户端是在同一个包里的,但是在 webpack4 里它们是分开的,所以在 webpack4 里要通过命令 yarn add -D webpack webpack-cli 去下载 webpack,同时安装 webpack-cli。

命令:  yarn add -D webpack webpack-cli 

 

新建一个 html 文件

命令:     touch index.html     

 

新建一个 src 文件

命令:     mkdir src    

 

在 src 目录下新建一个 components

命令:    mkdir components     

 

使用 vscode 打开文件 0812

 

可以在 components 目录下新建文件,我这里新建一个 xwh.js,然后编辑 xwh.js

可以从 vue/dist/vue.esm 引入 Vue,vue.esm 支持 es module 的 import...from 语句,所以引入这个。

(我后来运行代码时报错了,上网搜索后发现需要引入 vue,命令:npm i vue -S)

 

接着,新建一个 vm,传入各种配置。注册一个组件 components,局部注册一个 xwh 组件,在 data 里 return 一个 msg,在 components 里的写 template 。在 components 外的 template 里将组件 xwh 挂载起来。

import Vue from "vue/dist/vue.esm";

const vm = new Vue({
    el: "#app",
    data: {},
    template: `
        <div>
            <xwh></xwh>
        </div>
    `,
    components: {
        xwh: {
            data() {
                return {
                    msg: "小许想要快点找到工作",
                };
            },
            template: `
                <div>
                    <h1>{{ msg }}</h1>
                </div>
            `,
        },
    },
});
xwh.js

 

在目录 0812 下新建一个 webpack.config.js, webpack.config.js 是一个 webpack 的默认配置文件。

在 webpack.config.js 里面写配置。首先,写向外暴露的东西。

首先设置模式,mode 有 3 个值可选:development、production、none(可参考官网或网络资料,官网:https://webpack.js.org/configuration/mode/, 网络资料:https://blog.csdn.net/cuipp0509/article/details/105329735/),主要区别就是打包时压缩跟不压缩,development 对应的是开发环境,不需要压缩,production 对应的是生产环境,需要压缩,这里设置为 none( 对应语句:mode:'none' )。

然后,要找入口,设置入口,入口就找 “./src/components/xwh.js” 这个路径下的( 对应语句:entry:'./src/components/xwh.js')。

然后,要找出口,设置打包输出的路径,首先通过 node 里面的 path 模块拿进来( 对应语句:const path = require('path'); ),然后指定 path 跟 filename( 对应语句:    output:{ path: path.resolve(__dirname'dist'), filename:'bundle.js' } )。至此,基本写好了一个 webpack 打包配置文件。

const path = require('path');
module.exports = {
    // 模式
    mode:'none',
    // 入口
    entry:'./src/components/xwh.js',
    // 打包输出的路径
    output:{
        path: path.resolve(__dirname, 'dist'),
        filename:'bundle.js'
    }
}
webpack.config.js

执行 webpack

命令:   npx webpack   

可以看到打包生成了一个目录 dist 跟文件 bundle.js

使用 bundle.js。打开 index.js,引入 bundle.js

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=d, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app"></div>
    <script src="./dist/bundle.js"></script>
</body>
</html>
index.html

页面表现:

页面显示了 xwh.js 里 msg 的值

现在把 msg 改一下,然后在浏览器刷新页面,会发现内容并没有发生变化

改了之后需要重新打包,重新打包才可以发生改变。

每更新一次就需要重新打包一次,很麻烦。引入 webpack-dev-server 可以解决这个问题,webpack-dev-server 用于开发调试,提供 web 服务,热更新,接口代理等。

命令:   yarn add -D webpack-dev-server   

执行 webpack-dev-server

命令:    npx webpack-dev-server   

在 xwh.js 中更改 msg,刷新页面后发现仍然没有实现实时更新。

之所以不能实时更新,是因为在 index.html 中引用 bundle.js 的路径错了,因为使用了 webpack-dev-server,所以路径在根目录下,修改路径后刷新页面后就能实现实时更新了。

现在,只要直接更改 msg 就实现在页面上实时更新。

在 xwh.js 中更改 msg,刷新页面后发现实现了实时更新。

 

webpack-dev-server 打包后的 js 文件是在内存里边维护的,内存里的文件有一个问题:如果服务器重启,内存里的数据就没了。

所以,如果是部署在生产环境时使用 webpack-dev-server 的话会出问题,因为服务器需要隔段时间进行重启,一重启内存里的数据就没了。

因此,在开发的时候,并不需要去生成文件,只需要在内存里维护一份。但是,在项目开发完毕之后,必须要生成文件,如果内存里维护一份,服务器重启之后内存里的文件就没了。

所以,使用 webpack 搭建 vue 开发环境是,需要去区分到底现在是在开发还是生产。

在 0812 目录下新建一个 config,在 config 下新建 webpack.development.js 跟 webpack.production.js。

编辑 webpack.development.js 跟 webpack.production.js

为了判断是开发还是生产,下面需要修改 webpack.config.js。

webpack 可以进行命令行的环境配置,可以在命令行中传入任何参数,这会在配置文件中映射为对应的参数。向外暴露一个函数,参数为 env,这个 env 是可以接收传入的值,如果没有传入参数则 env 为空对象。然后,设置入口文件为 xwh.js 。然后,判断传入的 env,如果是 development,就 require webpack.development.js,否则 require webpack.production.js,拿到文件要将它展开。

(扩展运算符的作用,网络资料:https://segmentfault.com/a/1190000016753384?utm_source=tag-newest

const path = require('path');

module.exports = (env) => {
    env = env || {};
    return {
        entry: "./src/components/xwh.js",
        ...env.development ? require('./config/webpack.development') : require('./config/webpack.production')
    };
}
webpack.config.js

传入参数 development

命令:   npx webpack --env.development   

传入参数 production

命令:   npx webpack --env.production       

 

上面实现了在命令行传入不同的参数调用不同的文件,但是这样不方便。可以在 package.json 里进行更改,设置如果是 dev 的话,设置为 webpack-dev-server 传入参数 env.development,如果是 build 的话,直接执行打包传入参数 env.production。

{
  "name": "0812",
  "scripts": {
    "dev": "webpack-dev-server --env.development --open",
    "build": "webpack --env.production"
  },
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "devDependencies": {
    "webpack": "^4.44.1",
    "webpack-cli": "^3.3.12",
    "webpack-dev-server": "^3.11.0"
  },
  "dependencies": {
    "vue": "^2.6.11"
  }
}
package.json

执行 dev

命令:    yarn dev    

执行 build

命令:    yarn build   

 

 

实现了判断是开发还是生产后,可以继续编写配置文件 webpack.development.js 跟 webpack.production.js。

为了与 vue 的结构尽量相同,删除之前生成的 dist 目录。

module.exports = {
    // 开发模式, 在内存里维护, 不需要压缩与生成文件
    mode:'development',
    // 打包输出的路径
    output:{
        filename:'bundle.js',
    },
};
webpack.development.js

const path = require('path');
module.exports = {
    // 生产模式
    mode:'production',
    // 打包输出的路径
    output:{
        path: path.resolve(__dirname, '../build'),
        filename:'bundle.min.js'
    }
}
webpack.production.js

执行 dev

命令:    yarn dev    

执行 build,生成文件

命令:    yarn build    

 

 

现在有一个问题,index.html 里面的 src 是写死的。生产时,打包后的引用的路径应该是 <script src="./build/bundle.min.js"></script> ,开发时,引用的路径应该是 <script src="/bundle.js"></script> 。每次都要手动去进行更改很麻烦。

解决的办法是连 html 也一起打包了,需要引入插件 html-webpack-plugin

首先,在 0812 文件夹下新建一个 public 目录,将 index.html 移动到 public 目录下。然后,将 index.html 里引用文件的语句删掉。

引入插件

命令:   yarn add -D html-webpack-plugin   

使用 html-webpack-plugin。在 webpack.development.js 里 require 它。

const htmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
    // 开发模式, 在内存里维护, 不需要压缩与生成文件
    mode:'development',
    // 打包输出的路径
    output:{
        filename:'bundle.js',
    },
    plugins: [
        new htmlWebpackPlugin({
            //模板文件
            template: "public/index.html",
            //文件名
            filename: "index.html",
        }),
    ],
};
webpack.development.js

在 webpack.production.js 里 require 它。

const path = require('path');
const htmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
    // 模式
    mode:'production',
    // 打包输出的路径
    output:{
        path: path.resolve(__dirname, '../build'),
        filename:'bundle.min.js'
    },    
    plugins: [
        new htmlWebpackPlugin({
            //模板文件
            template: "public/index.html",
            //文件名
            filename: "index.html",
        }),
    ],
}
webpack.production.js

执行生产环境下的,打包后会发现 build 目录下多了一个 index.html 文件,右键单击 index.html 选择 open with live server 在浏览器查看一下。如果此时更改 xwh.js 里 msg 的值,要重新执行命令 npx webpack 之后页面内容才会更新。

命令:   npx webpack    

执行开发环境下的。如果此时更改 xwh.js 里 msg 的值,页面内容也会随之改变。

命令:   yarn dev   

 

 

目前实现了生产模式跟开发模式的判断,也把 html 打包了。

目前存在一个问题,我们平时在做 vue 开发的时候用的是组件,组件的的扩展一般是 .vue,xwh.js 是 .js 显然不是 vue 开发环境,之前在 xwh.js 里的写法是 vue1.0 的写法,所以需要对 vue 的开发环境进行升级。

在 webpack 中,如果要识别除了 js 和 json 以外的文件,需要安装 loader 去识别。plugin 的主要作用是扩展功能。要识别什么文件就使用什么 loader,比如说,如果要识别 vue 文件,就用 vue-loader,如果要识别 css 文件,就用 css-loader。

取得 vue-html-loader。vue-html-loader 用于解析 vue2.0 组件里的是 template。

命令:   yarn add -D vue-html-loader   

取得 vue-loader。vue-loader 用于解析 vue 文件。

命令:   yarn add -D vue-loader    

取得 vue-template-comiler。vue-template-compiler 是个编译器,专门用来把 vue 里的东西分别编译出来,比如说分别编译出 html、css、js。

命令:   yarn add -D vue-template-compiler    

在 src/components 目录下新建文件 Xwh.vue,在 src 目录下新建 App.vue、main.js。

(这些文件的作用可以参考网络资料:https://blog.csdn.net/qq_34182808/article/details/86690193

编写 main.js。引进 vue.esm、App.vue,挂载 App.vue

import Vue from 'vue/dist/vue.esm';
import App from './App.vue';

new Vue({
    el:"#app",
    components:{
        App
    },
    template:`
        <div>
            <app></app>
        </div>
    `
})
main.js

编写 App.vue。

<template>
    <div>
        <xwh></xwh>
    </div>
</template>

<script>
import Xwh from './components/Xwh.vue';
export default {
    name: 'App',
    components:{
        Xwh
    }
}
</script>
App.vue

编写 Xwh.vue。

<template>
    <div>
        <h1>
            {{ msg }}
        </h1>
    </div>
</template>

<script>
export default {
    name: 'Xwh',
    data(){
        return{
            msg:'许许许'
        }
    }
}
</script>
Xwh.vue

将 webpack.config.js 的入口路径由 xwh.js 改为 main.js,写 loader 的规则,如果有 .vue 结尾的文件则用 vue-loader 处理。

rules 配置模块的读取和解析规则,通常用来配置 Loader,配置一项 rules 时大致可通过条件匹配、应用规则、重置顺序这几种方式完成,其中条件匹配是通过 test、include、exclude 三个配置项来选中 Loader 要应用的规则,应用规则是对选中的文件通过 use 配置项来应用 Loader,可以只应用一个 Loader 或者按照从右往左的顺序应用一组 Loader。

const path = require('path');

module.exports = (env) => {
    env = env || {};
    return {
        // entry: "./src/components/xwh.js",
        entry: "./src/main.js",
        module:{
            rules:[
                {test:/.vue$/, use:"vue-loader"}
            ],
        },
        ...env.development ? require('./config/webpack.development') : require('./config/webpack.production')
    };
}
webpack.config.js

因为需要识别 loader,写好组件之后,在 webpack.development.js 跟 webpack.production.js 引入 vue-loader。

 开发环境执行一下,命令:   yarn dev   

 

至此,通过各种配置文件与 loader ,已经基本实现了开发环境。

但是,存在一个问题,在实际的开发中可能会写一些样式,还可能需要处理路径问题。

下面使用 resolve 处理路径问题,在导入语句没带文件后缀时,Webpack 会自动带上后缀去尝试访问文件是否存在。resolve.extensions 用于配置在尝试过程中用到的后缀列表。设置 extension:['.js', '.json', '.vue'] 的话,当遇到  import App from './App'; 语句时,webpack 首先会寻找 ./App.js ,如果找不到的话,找 ./App.json,如果找不到的话,找 ./App.vue,如果找不到的话,报错。尝试把 App.vue 里导入的 vue 文件的后缀去掉,在命令行输入 yarn dev 没有报错,页面正常显示, 说明 resolve.extensions 设置成功。

const path = require('path');

module.exports = (env) => {
    env = env || {};
    return {
        entry: "./src/main",
        module:{
            rules:[
                {test:/.vue$/, use:"vue-loader"}
            ],
        },
        resolve:{
            extensions:['.js', '.json', '.vue']
        },
        ...env.development ? require('./config/webpack.development') : require('./config/webpack.production')
    };
}
webpack.config.js

可以设置 resolve.alias 来配置项通过别名来将原导入路径映射成一个新的导入路径。比如说,设置 resolve.alias 后,导入路径 import Vue from 'vue/dist/vue.esm'; 可以简写为 import Vue from 'vue'; 。在命令行输入 yarn dev 没有报错,页面正常显示, 说明 resolve.alias 设置成功。

 

 

如果想要设置样式,需要设置 css-loader style-loader。css-loader 作用是解析 css,style-loader 作用是生成一个内容最终解析为 css 代码。

命令:   yarn add -D css-loader      

命令:   yarn add -D style-loader    

在 webpack.config.js 写 loader 的规则,如果有 .css 结尾的文件则用 css-loader、style-loader 处理。

rules 配置模块的读取和解析规则,通常用来配置 Loader,配置一项 rules 时大致可通过条件匹配、应用规则、重置顺序这几种方式完成,其中条件匹配是通过 test、include、exclude 三个配置项来选中 Loader 要应用的规则,应用规则是对选中的文件通过 use 配置项来应用 Loader,可以只应用一个 Loader 或者按照从右往左的顺序应用一组 Loader。

const path = require('path');

module.exports = (env) => {
    env = env || {};
    return {
        entry: "./src/main",
        module:{
            rules:[
                {test:/.vue$/, use:"vue-loader"},
                //从右往左,先用 css-loader 读取 css,再用 style-loader 解析成css规则
                {test:/.css/, use:["style-loader", "css-loader"]}
            ],
        },
        resolve:{
            extensions:['.js', '.json', '.vue'],
            alias:{
                vue: 'vue/dist/vue.esm'
            }
        },
        ...env.development ? require('./config/webpack.development') : require('./config/webpack.production')
    };
}
webpack.config.js

现在可以写个样式看看能不能实现了。在 Xwh.vue 里写个 row 样式

<template>
    <div class="row">
        <h1>
            {{ msg }}
        </h1>
    </div>
</template>

<script>
export default {
    name: 'Xwh',
    data(){
        return{
            msg:'许许许'
        }
    }
}
</script>

<style scoped>
    .row{
         200px;
        height: 120px;
        line-height: 120px;
        margin: 0 auto;
        background-color: #f50;
        color: #ffffff;
        text-align: center;
    }
</style>
Xwh.vue

执行命令 yarn dev ,没有报错,网页有样式正常显示。

试试打包会不会有问题,先将之前生成的 build 目录删除,然后执行命令 yarn build。执行命令后发现没有问题,生成了 build 目录,打开 index.html 页面正常显示。

目前的文件目录结构如下:

 

至此,简单实现了使用 webpack 搭建 vue 开发环境,基本没有使用 vue-cli。

 

 

 

原文地址:https://www.cnblogs.com/xiaoxuStudy/p/13492608.html