通过Webpack 打包vue脚手架的初步教程

2,537 阅读8分钟

配置开发时的前端工程(vue-loader+webpack)

我们通过快捷键 ‘ctrl + ·’,也就是esc下面的小点,打开终端,先来用 npm init 来初始化项目,大家实验的时候直接敲回车就行了.

PS C:\Users\A\Desktop\reNew webpackVue> npm init 
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.

See `npm help init` for definitive documentation on these fields
and exactly what they do.

Use `npm install <pkg>` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
package name: (renew-webpackvue)
version: (1.0.0)
description:
entry point: (index.js)
test command:
git repository:
keywords:
author:
license: (ISC)
About to write to C:\Users\A\Desktop\reNew webpackVue\package.json:

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


Is this OK? (yes)

这个时候细心的话会发现目录下面多一个package.json的文件,这个文件就是项目的配置文件。

image.png

因为我们用到了vue以及webpack,所以需要安装两个依赖包,还有段落标题中的vue-loader,这个是为了用webpack加载.vue文件,并编译成浏览器能认识的js文件,我们先来执行这样的指令,注:我们这里是demo,所以这里就不区分是否是dev-dependency了。(详情可以参考www.cnblogs.com/ayseeing/p/…)

npm i webpack vue vue-loader
PS C:\Users\A\Desktop\reNew webpackVue> npm i webpack vue vue-loader

added 118 packages, and audited 119 packages in 16s

13 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

安装完成之后可能会出现一些waring,这个waring其实就是告诉我们在安装vue-loader的同时必须要安装css-loader,这里我们想它继续安装完成就可以了。

npm WARN vue_web@1.0.0 No description
npm WARN vue_web@1.0.0 No repository field.

这两个是我们项目初始化的时候由于都是回车回车,缺少一些描述,无需关心。

npm WARN optional SKIPPING OPTIONAL
npm WARN notsup SKIPPING OPTIONAL

这两个是告诉我们项目初始化时候哪些是可选择安装的,哪些是可以不安装的,继续执行

npm i css-loader
PS C:\Users\A\Desktop\reNew webpackVue> npm i css-loader

up to date, audited 119 packages in 2s

13 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

好,到这里,我们项目的大概的初始化工作就完成了。接下来我们就基于这样的目录,填充一下更丰富的细节。

我们在工程目录下新建一个src文件夹用来存放源文件,并新建一个app.vue的文件:

image.png

app.vue代码如下:


<template>
  <div id="text">
    {{text}}
  </div>
</template>
 
<script>
  export default {
    data() {
      return {
        text: 'hello world'
      }
    }
  }
</script>
 
<style>
  #text {
    color: blueviolet;
    font-family: fangsong;
  }
</style>

大家都知道,浏览器其实只能够识别一些简单的文件,像js,css,html,img,font,但是如何让浏览器识别vue文件呢?

webpack配置

1. 输入输出

到这其实我们应该有一些认知了,webpack其实就是一个帮我们打包的工具。接下来我们在工程目录下新建一个webpack.config.js文件。

image.png

大家都知道,webpack是用来打包的工具
所以,接下来我们在新建的webpack.config.js里面做文章,配置webpack的入口和出口,让浏览器去访问,让webpack去打包并输出。

在src目录下新建一个index.js的文件作文工程的入口文件。

image.png

然后我们在index.js里面写一些内容,代码中我都做了注释,大家应该一眼就能看懂
index.js:

//这是工程的入口文件
import Vue from 'vue';
import App from './app.vue';
 
const root = document.createElement('div')
document.body.appendChild(root)
 
//mount就是讲我们的App挂载到root这样一个根节点中去
new Vue({
  render: (h) => h(App)
}).$mount(root)

我们这时候发现,浏览器要想运行这段代码,那是不可能的,因为浏览器不认识vue,更不认识new Vue,所以webpack要登场了。我们在webpack.config.js里配上entry入口和out出口,表示webpack文件会将将entry路径下的文件,打包到out的路径,

具体如下:
webpack.config.js:

const path = require("path");//nodejs里面的基本包,用来处理路径
 
//__dirname表示文件相对于工程的路径
module.exports ={
  entry: path.join(__dirname, 'src/index.js'),
  output: {
    filename: 'bundle.js',
    path: path.join(__dirname, 'dist')
  }
}

这里代码就不多说了,都有注释,这里卖个关子,也是经常会发生的场景,就是这里的join和resolve这两个函数的用法和区别,最好去官网看一下说明,直通车webpack.js.org/,英文不好的同学可以去…

好上面的代码就是做了这样一件事,将src下的index.js文件以js的形式打包到dist目录下的bundle.js中去。大家有疑问了,这两个目录我还没有新建呢!没有关系out属性中定义的路径如果没有的话,webpack会自动创建的,我们需要做的是就是新建src目录并添加index.js文件。那这个动作我们已经新建完成了,不记得的同学返回文章内容再看看。

这时候我们打开package.json文件添加一句:

"build": "webpack --config webpack.config.js"

image.png

很多有经验的同学应该都用过npm run build 这段指令,之后webpack帮我们干的一些事情,执行我们新建的webpack.config.js文件。注意:这里我们使用webpack来执行指令,同样可以在终端执行这段指令,但是我们要清楚在终端直接执行build后面的指令会出现一个问题,如我们在终端执行该指令,意味着使用的是全局的webpack,但是我们写在package.json文件下的话,意味着执行工程下面的局部wepackage,全局和局部可能会版本不一样,所以为了避免不必要的麻烦,我们在package.json文件下执行,也就是说使用的局部的webpack来打包。

好到这里,我们编译打包输入输出的相关配置已经完成,我们先执行一下:npm run build。可能有经验的小伙伴会发现还有一些配置没有完成,没关系,我们一步步来,带着错误把问题一个一个解决。

npm run build
PS C:\Users\A\Desktop\reNew webpackVue> npm run build

> renew-webpackvue@1.0.0 build      
> webpack --config webpack.config.js

CLI for webpack must be installed.
  webpack-cli (https://github.com/webpack/webpack-cli)

We will use "npm" to install the CLI via "npm install -D webpack-cli".
Do you want to install 'webpack-cli' (yes/no): yes

由于我使用的是webpack4,所以这里必须要安装一下cli。这里有人就问了,不是不用cli的嘛,怎么要安装这个包。如果你有这样的想法,证明你有自己用过cli搭建过vue项目框架的一些经验。我们知道用cli脚手架搭建出来的项目结构应该是这样的:

该图来源于网络,我们这里安装这个cli包是因为webpack4之后强制要求安装的,但是我们并没有通过该工具来初始化整个工程,所以建出来的目录也是不一样的,所以大家仔细想想就明白了。好了,接下来直接yes就可以,安装完成之后,再执行一下 npm run build,有些不需要再执行,但没有关系,反正都会报错:

image.png

这个错误呢就是告诉我们,需要为app.vue这个文件声明一个loader,因为webpack只支持js类型的文件,像这种vue文件是不支持的,所以我们要使用一些工具,来帮助它认识超出它理解范畴的语法。接下来便到了我们的module环节。

2. Module

由于webpack存在这样的一个限制,我们就需要来使用一些工具,我们在webpack.config.js里添加module配置项

webpack.config.js:

const path = require("path");//nodejs里面的基本包,用来处理路径
 
//__dirname表示文件相对于工程的路径
module.exports ={
  entry: path.join(__dirname, 'src/index.js'),
  output: {
    filename: 'bundle.js',
    path: path.join(__dirname, 'dist')
  },
  module: {
    rules: [
       {//通过vue-loader来识别以vue结尾的文件
         test: /.vue$/, 
         loader: 'vue-loader'
       }
    ]
  }
}

好添加完成之后,再次执行 npm run build 指令。

image.png

好,又报错了,这时候的错误是告诉我使用vue-loader的方式不正确。Vue-loader在15.*之后的版本都是 vue-loader的使用都是需要伴生 VueLoaderPlugin的,所以我们这里再来修改一下。这里会使用plugin属性,不了解的同学可以先跳过,也可以去官网查看一下这个属性的作用,这里我就先不介绍了。我们在package.config.js文件中添加VueLoaderPlugin,代码如下:

const path = require("path");//nodejs里面的基本包,用来处理路径
const VueLoaderPlugin = require('vue-loader/lib/plugin');
 
//__dirname表示文件相对于工程的路径
module.exports ={
  entry: path.join(__dirname, 'src/index.js'),
  output: {
    filename: 'bundle.js',
    path: path.join(__dirname, 'dist')
  },
  plugins: [
    // make sure to include the plugin for the magic
    new VueLoaderPlugin()
],
  mode:'none',
  module: {
    rules: [
       {//通过vue-loader来识别以vue结尾的文件
         test: /.vue$/, 
         loader: 'vue-loader'
       }
    ]
  }
}

再次执行一次 npm run build 还会报错,哈哈,到这有人会抱怨啦,是不是没玩没了啦。不用担心,保证这个问题解决完之后就可以啦。先看错误信息

不知道大家还记不记的我在app.vue文件中用“style标签嵌入”的方的式写css样式了

image.png

但是webpack并没有处理css的能力,所以我们还需要在moudle添加rules配置项,如下

const path = require("path");//nodejs里面的基本包,用来处理路径
const VueLoaderPlugin = require('vue-loader/lib/plugin');
 
//__dirname表示文件相对于工程的路径
module.exports ={
  entry: path.join(__dirname, 'src/index.js'),
  output: {
    filename: 'bundle.js',
    path: path.join(__dirname, 'dist')
  },
  plugins: [
    // make sure to include the plugin for the magic
    new VueLoaderPlugin()
],
  mode:'none',
  module: {
    rules: [
       {//通过vue-loader来识别以vue结尾的文件
         test: /.vue$/, 
         loader: 'vue-loader'
       },
       {//通过vue-loader来识别以vue结尾的文件
        test: /.css$/, 
        //css的处理方式不同,有嵌入在页面style标签里的,有从外部文件引入的,我们这里用use来声明
        use: [
          'style-loader',//接受潜在页面内部的style标签的文件。
          'css-loader'
        ]
      }
    ]
  }
}

好了,别忘了执行一下,

 npm i style-loader

因为之前没有安装过这个包,否则又要报错了。这部分属于配置静态资源的部分了,这里遇到了问题,就先介绍了。我们最后执行一下 npm run build 指令,不出意外的话,应该是这样的:

image.png

webpack配置项目加载各种静态资源及css预处理器

1. 静态资源

上一张我们详细使用了webpack加载并打包vue文件,以及最后处理的css文件,就针对静态资源这块,我们可以稍微更详细地了解一下。

好,在上一张的末尾,我们接触了css样式加载,我们稍微复习一下,大家也可以回头在巩固一下。

image.png

这里用了use属性而不是loader属性,是因为我们处理css文件的方式有多种,所以这里出多种方式的css加载需要用到use属性,所以这里用到了use,style-loader也就是处理html文件内部的style标签内的css样式,也就是我们俗称的内联,css-loader处理的是从文件外部引入的css文件,这里大家简单了解一下。

然后我们的图片怎么做呢?我相信大家举一反三的能力比我强多了,我们加载图片用到的loader叫‘url-loader’,它的作用是将我们的图片转换成一个base64的字串存放于我们打包生成的js里面,而不是重新生成一个文件。对于一些小的文件,几kb的文件可以帮助我们减少过多的http请求。那么url-loader其实封装了我们的file-loader,file-loader其实是将文件进行处理后换个名字存放于另一个地方。那么我们先看下配置:

const path = require("path");//nodejs里面的基本包,用来处理路径
const VueLoaderPlugin = require('vue-loader/lib/plugin');
 
//__dirname表示文件相对于工程的路径
module.exports ={
  entry: path.join(__dirname, 'src/index.js'),
  output: {
    filename: 'bundle.js',
    path: path.join(__dirname, 'dist')
  },
  plugins: [
    // make sure to include the plugin for the magic
    new VueLoaderPlugin()
],
  mode:'none',
  module: {
    rules: [
       {//通过vue-loader来识别以vue结尾的文件,正则表达式中的点需要转义
         test: /\.vue$/, 
         loader: 'vue-loader'
       },
       {//通过vue-loader来识别以vue结尾的文件
        test: /\.css$/, 
        //css的处理方式不同,有嵌入在页面style标签里的,有从外部文件引入的,我们这里用use来声明
        use: [
          'style-loader',//接受潜在页面内部的style标签的文件。
          'css-loader'
        ]
      },
      {//处理图片文件
        test: /\.(gif|jpg|jpeg|png|svg)$/ ,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 1024,
              name: '[name]-aaa.[ext]'
            }
          },
        ]
      }
    ]
  }
}

我们这里同样使用的use属性,不同的是数组里面使用的对象,因为我们对图片还需要进行一些更细化的配置,像图片的大小(limit),文件名称(name)有时都是需要进行配置的,所以这里使用了对象。下面呢,我们将使用到的loader安装一下。

npm i url-loader file-loader

我们安装完成了之后,所有的包是可以通过import来使用的。

接下来我们介绍一下图片的loader,新建一个assets目录,然后放几张图片进去,并同时新建一个styles目录新建一个test样式

image.png

图片大家可以自行下载,css就简单的给body设置了样式:

test.css:

body{
  color: red;
  background-image: url('../images/logo.png');
}

并且将我们项目的入口文件添加几行代码:

//这是工程的入口文件
import Vue from 'vue';
import App from './app.vue';
 
import './assets/styles/test.css';
import './assets/images/vue.png'
 
const root = document.createElement('div')
document.body.appendChild(root)
 
//mount就是讲我们的App挂载到root这样一个根节点中去
new Vue({
  render: (h) => h(App)
}).$mount(root)

好,我们现在执行一下npm run build 指令,可以看到webpack将图片打包成base64字串存放于js中,并且重新生成了新的文件

image.png

配置信息的参数“limit=1024”表示将所有小于1kb的图片都转为base64形式,而我们的图片的大小:

image.png

都超过了1KB,webpack表示不是我的锅,我不背...

我们将limit稍微改大一点设置100k,按照理论小一点的图片应该会被处理成base64的图片。我们再次执行一下npm run build

2. css预处理

我们经常听到过 sass less style-component这些比较火热的css预处理器,那这些我们webpack能不能处理呢?答案是肯定的。

这里我给大家推荐一款预处理器-stylus,大家多多少少听过或者使用过。我们新增一个配置项,注意:我们这里新增了stylus-loader,所以需要将这个安装包执安装,由于stylus-loader这个包依赖于stylus这个包,所以我们这里执行安装指令:

npm i stylus-loader stylus

webpack.config.js 代码更新如下:

const path = require("path");//nodejs里面的基本包,用来处理路径
const VueLoaderPlugin = require('vue-loader/lib/plugin');
 
//__dirname表示文件相对于工程的路径
module.exports ={
  entry: path.join(__dirname, 'src/index.js'),
  output: {
    filename: 'bundle.js',
    path: path.join(__dirname, 'dist')
  },
  plugins: [
    // make sure to include the plugin for the magic
    new VueLoaderPlugin()
],
  mode:'none',
  module: {
    rules: [
       {//通过vue-loader来识别以vue结尾的文件,正则表达式中的点需要转义
         test: /\.vue$/, 
         loader: 'vue-loader'
       },
       {//通过vue-loader来识别以vue结尾的文件
        test: /\.css$/, 
        //css的处理方式不同,有嵌入在页面style标签里的,有从外部文件引入的,我们这里用use来声明
        use: [
          'style-loader',//接受潜在页面内部的style标签的文件。
          'css-loader'
        ]
      },
      {
        test: /\.styl$/, 
        use: [
          'style-loader',
          'css-loader',
          'stylus-loader'
        ]
      },
      {//处理图片文件
        test: /\.(gif|jpg|jpeg|png|svg)$/ ,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 1024 * 20, //将所有小于1kb的图片都转为base64形式
              name: '[name]-aaa.[ext]'
            }
          },
        ]
      }
    ]
  }
}

我们新建一个styls,我们想要在vscode中使用stylus需要安装一个插件:

image.png

安装完成之后,重新启动就可以了。我们新建的styl文件如下:

image.png

代码:

test-stylus-.styl

body 
  font-size  20px

这种写法是不是看上去落落大方,透露一股简约风范。我们再将这个styl文件在入口文件中引用进来。

入口文件 index.js

//这是工程的入口文件
import Vue from 'vue';
import App from './app.vue';
 
import './assets/styles/test.css';
import './assets/styles/test-stylus.styl';
import './assets/images/vue.png';
 
const root = document.createElement('div')
document.body.appendChild(root)
 
//mount就是讲我们的App挂载到root这样一个根节点中去
new Vue({
  render: (h) => h(App)
}).$mount(root)

接着我们就可以编译一下,继续执行npm run build 指令编译

webpack配置webpack-dev-server

这个包是咱们在开发环境用的包处理工具,我们这里先install这个包。

npm i webpack-dev-server

这部分内容是在换了个网络环境下完成的,因为移动的网速度不快,这里使用了cnpm来安装。使用方式就是在package.json文件里添加:

 "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack --config webpack.config.js",
    "dev": "webpack-dev-server --config webpack.config.js"
  }

这里添加完dev指令后需要到webpack.config.js下修改一部分内容来专门适应我们的开发环境。

首先我们需要添加target属性,将其设置为‘web’,由于我们使用的是浏览器编译平台,所以这里设置为web,这也是webpack这个属性的默认设置,所以写不写无所谓。更多的target属性值我这里给他家提供腾讯云的解释:cloud.tencent.com/developer/s…

image.png

接下来我们需要区分全局的一个环境,很容易就想到需设置一个全局的环境变量来做区分控制,我们在build指令后面添加代码

我们如果不想区分不同系统,写一套代码来适应多个系统,我们这里就使用到了 cross-env,我们在指令前面添加cross-env

当然这个包也是需要安装的,执行

cnpm i cross-env

最后我们还需要给dev下的指令配置一个变量值,用来区分两套环境

  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "cross-env NODE_ENV=production webpack --config webpack.config.js",
    "dev": "cross-env NODE_ENV=development webpack-dev-server --config webpack.config.js"
  }

这里完成之后我们就可以在webpack.config.js文件里面进行判断了。

我们现在文件下新建一个变量

const isDev = process.env.NODE_ENV === 'development';

我们启动时设置的脚本变量都是可以通过process.env这个对象来获取的。更多关于process.env的内容可以到webpack.docschina.org/guides/envi… 读阅

这里我们判断如果是dev环境的话,我们就给webpack.config.js添加一些配置。

if(isDev){
  config.devServer = {
    port: 8080,
    host: '0.0.0.0',
    overlay: {
      erros: true,
    }
  }
}

首先我们给devServer属性添加一个port,因为我们新建的是一个服务,所以肯定要一个端口,接下来我们配置host,这里使用‘0.0.0.0’也是有好处的。这样可以通过127.0.0.1(本地默认地址)来进行访问,同时还可以在别人的机器上来访问,因为如果设置成‘localhost’的话通过ip是不能访问的。这里大家了解一下,更多相关derserver内容可以去这里参考:www.webpackjs.com/configurati… overlay属性是在我们编译的过程中能够让任何的错误都显示到网页上面。最后我们加完了这些基础的配置之后回过头来发现,我们好像配置的只是js、css、img文件,没有html页面去容纳它们。这个时候我们用到一个webpack的一个插件html-webpack-plugin,我们照样来安装一下它:

cnpm i html-webpack-plugin

并且在webpack.config.js文件的头部将它require进来,同时在plugin中新建。这里推荐一篇博客关于html-webpack-plugin的,大家可以参阅一下www.cnblogs.com/wonyun/p/60…

到这里我们基本的配置就完成了,最后需要了解一下webpack.DefinePlugin,我们在代码中的plugin里添加:

 plugins: [
    // make sure to include the plugin for the magic
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: isDev ? '"development"' : '"production"'
      }
    }),
    new VueLoaderPlugin(),
    new HTMLPlugin()
],

这里我们用到了webpack,所以需要将 webpack 这个变量引用进来。

说到这里,理论上我们已经完成的本地开发环境的编译,通过npm run dev就可以进行编译,我们来试验一下。

执行:npm run dev

这里在浏览器里面输入localhost:8000会出现:

说明我们npm run dev已经启动成功了。

这里我们再介绍一些devserver其他的一些配置。

image.png

文章出处引自于此,更详细的内容,希望大家参考: blog.csdn.net/u013368397/…