搭建基于webpack4.0的vue项目,这篇文章就够了

本文意在带领读者简单搭建基于webpack4.0环境下的Vue项目,在此过程中熟悉webpack以及vue的简单用法,请一定要按照步骤一步一步进行,循序渐进,从依赖包安装到webpack配置到vue单文件组件的引用到最后打包发布一条龙服务包各位看官满意;

下面坐端正,手放在电脑上,看老师,Let's go,整个过程预计在30min-45min;
最后会附上源代码下载链接

第一步:安装webpack

首先自行选择路径创建项目
并新建一个文件夹 webpack-vue

全局安装webpack,安装之前先检查全局是否已经安装并且确定版本

本文中 webpack 版本为 4.23.0,webpack-cli 版本为 3.1.2

检查版本命令为:

F:\vue-learns\webpack-vue>webpack -v
4.23.0

F:\vue-learns\webpack-vue>webpack-cli -v
3.1.2

如果没有安装请自行安装,命令如下:

yarn add webpack webpack-cli -g

第二步:项目初始化

进入项目目录:

cd vue-learns
cd webpack-vue

yarn init -y
//新建package.json
//和npm功能类似,如果还没安装yarn,网上有大量教程在此不赘述

安装vue webpack webpack-dev-server

yarn add vue (--save可省略)
yarn add webpack webpack-dev-server --dev
//--save 的意思是将模块安装到项目目录下,并在package文件的dependencies节点写入依赖。
//--dev 的意思是将模块安装到项目目录下,并在package文件的devDependencies节点写入依赖。

在项目根目录下新建index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    
</body>
</html>

在项目根目录下新建webpack.config.js

var path = require('path');
var webpack = require('webpack');

module.exports = {};

新建src文件夹目录,并且在src下新建main.js,此时目录结构如下:


webpack的思想就是一切皆模块,官方推荐使用commonJS规范,这使得我们浏览器端也可以使用commonJS的模块化写法 :module.exports = {}

src目录下新建一个utils.js

module.exports = function say() {
    console.log('hello world');
}

main.js :

var say = require('./utils');
say();

webpack.config.js:

var path = require('path');
var webpack = require('webpack');

module.exports = {
  entry: './src/main.js', // 项目的入口文件,webpack会从main.js开始,把所有依赖的js都加载打包
  output: {
    path: path.resolve(__dirname, './dist'), // 项目的打包文件路径
    publicPath: '/dist/', // 通过devServer访问路径
    filename: 'build.js' // 打包后的文件名
  },
  devServer: {
    historyApiFallback: true, //historyApiFallback设置为true那么所有的路径都执行index.html。
    overlay: true // 将错误显示在html之上
  }
};

运行:

webpack4.0 可能会运行报错,需要重新安装 yarn add -D webpack-cli

yarn run dev

可以发现浏览器自动打开一个http://localhost:8080/ 的页面 F12打开控制台可以看到有hello world打出
随意修改utils.js,可以发现浏览器会自动刷新

如果我们希望看打包后的bundle.js文件,运行

yarn run build
  • webpack默认不支持转码es6,但是import export这两个语法却单独支持。所以我们可以改写前面的模块化写法

utils.js:

export default function say() {
    console.log('hello world ');
}

第三步:引入vue

main.js:

import Vue from 'vue';

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

index.html:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <div id="app">
        {{message}}
    </div>
    <script src="/dist/build.js"></script>
    
</body>

</html>

webpack.config.js :

var path = require('path');
var webpack = require('webpack');

module.exports = {
    entry: './src/main.js',
    output: {
        path: path.resolve(__dirname, './dist'),
        publicPath: '/dist/',
        filename: 'build.js'
    },
    devServer: {
        historyApiFallback: true,
        overlay: true
    },
    resolve: {
        alias: {
            'vue$': 'vue/dist/vue.esm.js'
        }
    }
};

重新运行npm run dev,可以看到,清一下缓存(ctrl+shift+delete),页面正常显示了'Hello Vue!'


第四步:引入scss和css

  • webpack默认只支持js的模块化,如果需要把其他文件也当成模块引入,就需要相对应的loader解析器
yarn add node-sass css-loader vue-style-loader sass-loader --dev

webpack.config.js:

var path = require('path');
var webpack = require('webpack');

module.exports = {
    entry: './src/main.js',
    output: {
        path: path.resolve(__dirname, './dist'),
        publicPath: '/dist/',
        filename: 'build.js'
    },
    devServer: {
        historyApiFallback: true,
        overlay: true
    },
    resolve: {
        alias: {
            'vue$': 'vue/dist/vue.esm.js'
        }
    },
    module: {
        rules: [
            { //匹配后缀名为css的文件,然后分别用css-loader,vue-style-loader去解析
              //解析器的执行顺序是从下往上(先css-loader再vue-style-loader)
                test: /\.css$/,
                use: [
                    'vue-style-loader',
                    'css-loader'
                ],
            },
            {
                test: /\.scss$/,
                use: [
                    'vue-style-loader',
                    'css-loader',
                    'sass-loader'
                ],
            },
            {
                test: /\.sass$/,
                use: [
                    'vue-style-loader',
                    'css-loader',
                    'sass-loader?indentedSyntax'
                ],
            }
        ]
    }
};
  • 注意:因为我们这里用vue开发,所以使用vue-style-loader,其他情况使用style-loader
    css-loader使得我们可以用模块化的写法引入css,vue-style-loader会将引入的css插入到html页面里的style标签里

我们现在在src目录下新建style目录,style目录里新建common.scss
common.scss:

body {
  background: #fed;
}

main.js:

import './style/common.scss';

重新 yarn run dev ,可发现样式生效

第五步 : 使用babel转码

ES6的语法大多数浏览器依旧不支持,bable可以把ES6转码成ES5语法,这样我们就可以大胆的在项目中使用最新特性了

yarn add babel-core babel-loader babel-preset-env babel-preset-stage-3 --dev

在项目根目录新建一个.babelrc文件

{
  "presets": [
    ["env", { "modules": false }],
    "stage-3"
  ]
}

webpack.config.js添加一个loader

{
    test: /\.js$/,
    loader: 'babel-loader',
    exclude: /node_modules/  
}
//exclude表示忽略node_modules文件夹下的文件,不用转码

现在我们来试下async await语法吧
utils.js

export default function getData() {
    return new Promise((resolve, reject) => {
        resolve('ok');
    })
}

main.js

import getData from './utils';
import Vue from 'vue';

import './style/common.scss';

var app = new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue!'
  },
  methods: {
    async fetchData() {
      const data = await getData();
      this.message = data;
    }
  },
  created() {
    this.fetchData();
  }
});

第六步 : 引入图片资源

把图片也当成模块引入

yarn add file-loader --dev

webpack.config.js添加一个loader

{
    test: /\.(png|jpg|gif|svg)$/,
    loader: 'file-loader',
    options: {
        name: '[name].[ext]?[hash]'
    }
}

在src目录下新建一个img目录,存放一张图片logo.png

main.js:

import getData from './utils';
import Vue from 'vue';

import './style/common.scss';


Vue.component('my-component', {
  template: '<img :src="url" />',
  data() {
    return {
      url: require('./img/logo.png')
    }
  }
})

var app = new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue !'
  },
  methods: {
    async fetchData() {
      const data = await getData();
      this.message = data;
    }
  },
  created() {
    this.fetchData()
  }
});

index.html:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
<div id="app">
    {{message}}
    <my-component/>
</div>
<script src="/dist/build.js"></script>

</body>

</html>

在此刻我在重新 yarn run dev 的时候我报了一个如下的错误,应该是由版本引起的


解决方案:

yarn add babel-loader@7 --dev

安装完后重新 yarn run dev 便可以看见,图片也被正确加载了

第七步:单文件组件

在前面的例子里,我们使用 Vue.component 来定义全局组件
在实际项目里,更推荐使用单文件组件

yarn add vue-loader vue-template-compiler --dev

添加一个loader:

{
    test: /\.vue$/,
    loader: 'vue-loader',
    options: {
        loaders: {
            'scss': [
                'vue-style-loader',
                'css-loader',
                'sass-loader'
            ],
            'sass': [
                'vue-style-loader',
                'css-loader',
                'sass-loader?indentedSyntax'
            ]
        }
    }
}

在src目录下新建一个App.vue

<template>
    <div id="app">
        <h1>{{ msg }}</h1>
        <img src="./img/logo.png">
        <input type="text" v-model="msg">
    </div>
</template>

<script>

  import getData from './utils';

  export default {
    name: 'app',
    data () {
      return {
        msg: 'Welcome to Your Vue.js'
      }
    },
    created() {
      this.fetchData();
    },
    methods: {
      async fetchData() {
        const data = await getData();
        this.msg = data;
      }
    }
  }
</script>

<style lang="scss">
    #app {
        font-family: "Avenir", Helvetica, Arial, sans-serif;

        h1 {
            color: #CC3333;
        }
    }
</style>

main.js:

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

import './style/common.scss';

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

index.html:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <div id="app"></div>
    <script src="/dist/build.js"></script>
</body>

</html>

此处在yarn run dev 的时候又报错了


分析:
. 参考官方文档 https://vue-loader.vuejs.org/migrating.html#a-plugin-is-now-required
. Vue-loader在15.*之后的版本都是 vue-loader的使用都是需要伴生 VueLoaderPlugin的,

解决:
webpack.config.js中加入 :

最后发现控制台会报一个错误regeneratorRuntime is not defined,因为我们没有安装babel-polyfill

yarn add babel-polyfill --dev

然后修改webpack.config.js的入口

entry: ['babel-polyfill', './src/main.js'],

重新 yarn run dev ,可以发现单文件被正确加载了

第八步 source-map

在开发阶段,调试也是非常重要的一项需求。
App.vue:

created() {
    this.fetchData();
    console.log('23333');
}

我们点击进入这个console的详细地址:



进入的是打包后的build.js,我并不知道是在哪个组件里写的,这就造成了调试困难
这时就要修改webpack.config.js

module.exports = {
    entry: ['babel-polyfill', './src/main.js'],
    // 省略其他...

    devtool: '#eval-source-map'
};

重新yarn run dev
进入控制台,这次调试,它直接返回那个组件的源代码了,这不是被打包过的!

第九步 打包发布

我们先试着yarn run build打包一下文件



会发现,打包后的build.js非常大,有1M多 并且提示了 [big]

在实际发布时,会对文件进行压缩,缓存,分离等等优化处理

webpack4.x下,压缩代码不在webpack.config.js中写plugins: [ new webpack.optimize.UglifyJsPlugin() ],而是在package.json中的script下面写:

"scripts": {
    "build": "webpack --mode development"
},
var path = require('path');
var webpack = require('webpack');

module.exports = {
    // 省略...
    optimization: {
        splitChunks: {
         chunks: 'all'
         }
     }
  }

再次重新打包

可以看见,压缩效果非常明显!
至此,一个非常简单的vue开发环境搭建成功。

本文仅做参考,并且同时我也参考了很多文章也踩了一些坑(不同版本的功能是大坑啊)

读者可以自行了解相关知识,这里只是带领大家了解最基础的webpack配置。

后续的vue学习便可以在此基础上继续深入了,加油

源代码链接:
https://github.com/a307420929/webpack-vue

欢迎批评指正

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容