阅读 747

从零开始的vue-cli(简易版)

你能学到什么?

这里将介绍如何从零开始搭建一套包含调试,构建的vue脚手架,其中主要是对webpack的学习,以及现在一些常用的集成在脚手架中前端功能的使用比如:babel,代码压缩,代码热更新等等。本文适合掌握了前端基础以及vue相关知识的程序猿观看学习,最主要的是要有颗热爱这个行业的心(滑稽),也请各位大神指教指教,不喜勿喷,如果对你起到了一丝丝的帮助也请给咱点个赞~

安装依赖

安装webpack以及webpack-cli(使用webpack必须的依赖)

npm i webpack webpack-cli
复制代码

安装webpack-dev-server(用于调试,热更新等)

npm i webpack-dev-server
复制代码

初始化项目

新建package.json

npm init -y
复制代码

新建index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>vue-cli-simple</title>
</head>
<body>
</body>
</html>
复制代码

新建src目录并且新建main.js用于做入口文件

在根目录新建webpack.config.js用于webpack配置

module.exports = {};
复制代码

最终项目结构为

webpack打包以及调试

首先在main.js中写入

alert('这是一个页面')
复制代码

接着将webpack配置文件webpack.config.js更改

const path = require('path');
module.exports = {
    entry: './src/main.js',
    output: {
        path: path.resolve(__dirname, './dist'),
        publicPath: '/dist/', 
        filename: 'app.js' 
    },
    devServer: {
        historyApiFallback: true,
        overlay: true
    }
};
复制代码

entry:要打包的js文件

path:最后生成文件的路径

publicPath:使用调试模式时文件的位置

filename:最后生成的文件名

最后修改index.html引入打包好的js,由于path,publicPath我们写的是相同的所以这边我们只要用/dist/app.js就都能访问(不管是调试模式还是最后打包出来)

index.html加上

<script src="/dist/app.js"></script>
复制代码

最后改动package.json加入调试以及打包的命令

"scripts": {
    "serve""webpack-dev-server --open --hot",
    "build""webpack --progress --hide-modules"
  }
复制代码

运行 npm run serve

并且当你改动main.js的值的时候会同步刷新(热更新)

运行 npm run build

Babel

首先babel我们知道是用来适配新语法的所以我们修改main.js,加入一些语法,如箭头函数,let

let babelTest= ()=>{
    alert('这里是babelTest方法')
}
babelTest()
复制代码

运行后可以找到app.js

所以如果是这样的话一些诸如ie或者老版本的浏览器就无法运行起来,所以我们来安装babel

npm install babel-loader @babel/core @babel/preset-env babel-polyfill
复制代码

在根目录创建.babelrc文件(用于配置),现在我们先放空

{}
复制代码

接着在改动webpack.config.js中加入

module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ['@babel/preset-env']
                    }
                }
            }
        ]
    }
复制代码

简单介绍一下这边的rules,webpack在进行编译的时候会读取rules选项,并根据里面的配置处理文件。

test说明需要处理的文件类型,exclude是要忽略的文件,use中就是处理的方法。

这里的配置就是处理所有的js文件,但是忽略所有node_modules中的js,最后使用babel-loader去处理匹配到的js文件。

现在再次运行

可以看到已经将代码修改好了。还有一点要提的是babel默认只转换新的JavaScript句法(syntax),而不转换新的API,比如async/await。若想要转化的话要使用babel-polyfill

npm install  babel-polyfill
复制代码

把webpack.config.js的entry改一下

entry: ['babel-polyfill''./src/main.js']
复制代码

用es6中的async/await试一下,改动main.js

function sendMes() {
    return new Promise((resolve, reject) => {
        resolve('这里是数据');
    })
}
async function getData(){
    const data = await sendMes();
    console.log(data)
}
getData()
复制代码

运行后

关于babel-polyfill的话,它提供一个环境让浏览器可以使用不支持的那些语法,比如旧的浏览器中不支持await,则babel-polyfill会在全局定义一个await并实现它,到最后浏览器就可以正常使用。

引入vue

安装vue

npm install vue
复制代码

改动main.js

import Vue from 'vue';

var app = new Vue({
  el: '#app',
  data: {
    message: '这里是vue'
  }
复制代码

改动index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>vue-cli-simple</title>
</head>
<body>
    <div id="app">
        {{message}}
    </div>
    <script src="/dist/app.js"></script>
</body>
</html>
复制代码

运行

不过由于vue引入时默认的是不带编译器的版本,所以没有办法解释模板,这个时候运行的话会报错,所以要把vue的版本转到带编译器的版本

在webpack.config.js加入

resolve: {
        alias: {
            'vue$''vue/dist/vue.esm.js'
        }
    }
复制代码

再次运行即可

添加scss与css

安装依赖

npm i node-sass css-loader vue-style-loader sass-loader
复制代码

在src目录下新建一个styles文件夹并在其中新建common.css

body{
    font-size: 30px;
}
复制代码

改动webpack.config.js

rules: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ['@babel/preset-env']
                    }
                }
            },
            {
                test: /\.css$/,
                use: [
                    'vue-style-loader',
                    'css-loader'
                ],
            }
        ]
复制代码

这边我们用了一个新的rule是关于css文件的处理,值得一提的是,如果use中有多个处理方法,那么会从下往上依此处理,这边就是先用css-loader加载css,再用vue-style-loader把加载好的样式加入近vue中。

修改main.js加入

import './styles/common.css';
复制代码

可以看到样式生效了

所以如果要加载scss的话,只要多一步将scss转化成css的loader即可(sass-loader) 改动webpack.config.js

 rules: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ['@babel/preset-env']
                    }
                }
            },
            {
                test: /\.css$/,
                use: [
                    'vue-style-loader',
                    'css-loader'
                ],
            },
            {
                test: /\.scss$/,
                use: [
                    'vue-style-loader',
                    'css-loader',
                    'sass-loader'
                ],
            }
        ]
复制代码

styles中创建scssTest.scss

body{
    div{
        color: red;
    }
    
}
复制代码

main.js中引入,再次运行即可看到效果

引入.vue文件

安装依赖

npm i vue-loader vue-template-compiler 
复制代码

改动webpack.config.js加入一个针对.vue文件的loader

{
    test: /\.vue$/,
    loader: 'vue-loader',
    options: {
        loaders: {
            'scss': [
                'vue-style-loader',
                'css-loader',
                'sass-loader'
            ]
        }
    }
}
复制代码

并且添加一个vueloader的插件,多说一句这里在vue-loader中又多加了一个针对scss的loader,使得我们可以在vue文件中使用scss。

const path = require('path');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
module.exports = {
...
plugins: [
        new VueLoaderPlugin()
    ]

...
}
复制代码

在src中新建App.vue

<template>
   <div>
       <p>{{ userInput }}</p>
        <input v-model="userInput">
   </div>
</template>

<script>
export default {
    data(){
        return{
            userInput:'测试'
        }
    }
}
</script>
<style scoped lang="scss">
div{
    p{
        color: blue
    }
}
</style>
复制代码

修改main.js

import Vue from 'vue';
import App from './App.vue';
import './styles/common.css';
import './styles/scssTest.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">
    <title>vue-cli-simple</title>
</head>
<body>
    <div id="app"></div>
    <script src="/dist/app.js"></script>
</body>
</html>
复制代码

运行

错误调试

我们在平常的开发中遇到的报错后面都会有详细的信息,如错误行数等,方便我们定位错误。而在webpack中输出的是编译过后的错误位置。现在我们在App.vue中输出一个值。

export default {
    data(){
        return{
            userInput:'测试'
        }
    },
    mounted(){
        console.log('测试')
    }

}
复制代码

可以看到是从一个未知的js中输出出来的,这样不利于我们调试,要解决这个问题我们改动webpack.config.js

module.exports = {
...
devtool: '#eval-source-map'
...
}
复制代码

再次运行的话

就知道在我们源码中的哪个部分了

打包

执行打包命令 npm run build

发现打包出来的js居然有1.68M的大小,原因是我们加入了调试时的提示以及未进行压缩

压缩使用webpack中的UglifyJSPlugin插件即可

npm install uglifyjs-webpack-plugin
复制代码

修改webpack.config.js,再加入一个插件

const path = require('path');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
module.exports = {
...
plugins: [
        new UglifyJSPlugin(),
        new VueLoaderPlugin()
    ]

...
}
复制代码

因为加入了错误调试的代码,我们需要将上一步所加的东西去除,但是为了调试的时候有,打包的时候没有就需要加入一个环境变量,安装

npm i cross-env --save-dev
复制代码

cross-env用于改变环境

改动package.json

"scripts": {
    "serve""cross-env NODE_ENV=development webpack-dev-server --open --hot",
    "build""cross-env NODE_ENV=production webpack --mode production  --progress --hide-modules"
  }
复制代码

这样webpack.config.js就可以通过判断process.env.NODE_ENV来进行区别

改动webpack.config.js,在最后加上

if (process.env.NODE_ENV === 'production') {
    module.exports.devtool = '';
}
复制代码

再次打包

发现我们的js只剩下了192k非常稳。

结语

了解了这简单版本的脚手架如何构建,总的来说webpack给前端带来便利性,工程性是前所未有的, 虽然慢慢有更好的方案开始代替它,但是他的思想还是值得我们去学习的。当然cli的构建远没有这么简单,不过有了雏形之后一点点完善它也是一种乐趣所在吧。