从零搭建 vue2 vue-router2 webpack4 工程

2018/9/1

《从零搭建 vue2 vue-router2 webpack3 工程》一样,以新手视角,详细介绍各个步骤内容,不深入讲步骤涉及的原理,主要介绍如何操作。

文中示例工程地址:https://github.com/qinshenxue/vue2-vue-router2-webpack4

初始化工程

新建工程目录 vue2-vue-router2-webpack4,在目录下执行npm init -y来创建一个 package.json,在 package.json 中先添加以下必要模块:

{
  "name": "vue2-vue-router2-webpack4",
  "version": "1.0.0",
  "devDependencies": {
    "vue": "^2.5.17",
    "vue-loader": "^15.4.1",
    "vue-router": "^3.0.1",
    "vue-template-compiler": "^2.5.17",
    "webpack": "^4.17.1",
    "webpack-cli": "^3.1.0",
    "webpack-dev-server": "^3.1.6"
  }
}

Webpack 4 开始,命令行工具(CLI)需要单独安装。

新建目录结构如下,新增的目录及文件先空着,后面的步骤会说明添加什么内容。

vue2-vue-router2-webpack4
    |-- package.json
    |-- index.html         // 访问首页
    |-- webpack.config.js  // Webpack 配置文件
    |-- src
        |-- views       // Vue 页面目录
        |-- main.js     // 入口起点
        |-- router.js   // vue-router 配置
        |-- app.vue     // Vue 根组件

配置 Webpack

Webpack 默认读取 webpack.config.js,文件名不能随便改,其中 entry 是必须配置的,构建时,output.filename是必需的。

module.exports = {
    mode: "development",
    entry: './src/main.js',
    output: {
        path: __dirname + '/dist', 
        publicPath: '/static/', 
        filename: 'build.js'
    }
}

Webpack 4 增加了 mode 配置项,支持配置"production" | "development" | "none"三个可选配置,默认为"production"

mode 的作用可以简单概括为把各个环境常用的配置缩减为一个配置。

配置为 development 背后实际上是包含了如下配置。

module.exports = {
 devtool: 'eval',
 plugins: [
   new webpack.NamedModulesPlugin(),   
   new webpack.NamedChunksPlugin(),   
   new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("development") })  // 设置环境变量为 '"development"'
 ]
}

配置为 production 背后实际上是包含了如下配置。

module.exports = {
  mode: 'production',
  plugins: [
    new UglifyJsPlugin(/* ... */),  // 压缩

    // 设置环境变量为 '"production"'
    new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("production") }),  

    // 作用域提升
    new webpack.optimize.ModuleConcatenationPlugin(),  

    new webpack.NoEmitOnErrorsPlugin() 
 ]
}

webpack-dev-server 不需要配置文件,直接使用其 CLI 提供的命令即可。

"scripts": {
  "dev": "webpack-dev-server --hot --open"
}

验证配置

在 index.html 中添加测试代码,引入打包后的 JavaScript 文件。

<body>
    Hello, Webpack 4.
    <br>
    <script src="/static/build.js"></script>
</body>

在 main.js 中添加测试代码。

// main.js
document.write('来自 main.js 的问候!')

执行下面的命令来安装依赖模块并启动本地服务器。

# 安装依赖模块
npm install

# 启动本地服务器
npm run dev

启动后浏览器会自动打开http://localhost:8080,如果控制台没有报错,页面正确显示 main.js 和 index.html 的内容,改动 main.js 后浏览器会自动刷新,则表示配置没问题。

Vue

新建页面。

在 views 目录下新建 index.vue。

<template>
    <div>
        这是{{page}}页面
    </div>
</template>
<script>
export default {
    data: function () {
        return {
            page: 'index'
        }
    }
}
</script>

配置路由

将 vue-router 实例化传入的参数提取到 router.js 作为路由配置文件。

import index from './views/index.vue'
export default {
    routes: [
        {
            path: '/index',
            component: index
        }
    ]
}

修改首页

在 index.html 添加 Vue 根实例的挂载元素。

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

修改入口

在 main.js 完成路由配置、初始化 Vue 实例。

import Vue from "vue"
import VueRouter from "vue-router"
import App from "./app.vue"
import routerConfig from "./router"
Vue.use(VueRouter)
const router = new VueRouter(routerConfig)
new Vue({
    el: "#app",
    router: router,
    render: h => h(App)
})

在根组件 app.vue 中添加路由链接、路由视图组件。

<template>
    <div>
        <div>
            <router-link to="/index">Home</router-link>
        </div>
        <div>
            <router-view></router-view>
        </div>
    </div>
</template>

配置 loader

配置 .vue 文件对应的 loader。

const VueLoaderPlugin = require('vue-loader/lib/plugin')

module.exports = {
    mode: "development",
    entry: './src/main.js',
    output: {
        path: __dirname + '/dist',
        publicPath: '/static/',
        filename: 'build.js'
    },
    module: {
        rules: [{
            test: /\.vue$/,
            use: ["vue-loader"]
        }]
    },
    plugins: [
        new VueLoaderPlugin()
    ]
}

vue-loader 从 v15.0.0 开始,配置需要引入vue-loader/lib/plugin,并在 plugins 中初始化。详细请参考官方文档 https://vue-loader.vuejs.org/zh/guide/#vue-cli

上面完成了访问一个页面所需要的步骤,接下来可以启动本地服务器(npm run dev)来测试能否正常访问/index。

支持 CSS

直接在 .vue 文件中使用 CSS 会提示You may need an appropriate loader to handle this file type.,CSS 对应的 loader 为css-loader

npm install css-loader -D

vue-loader v15.0.0 之前不需要配置 loader 就可以在 vue 文件中使用 CSS,需要用 import 或 require CSS 文件时才需要配置 loader,而 v15.0.0 之后均需要自己配置 loader 才不会报错。

{
    test: /\.css$/,
    use: ["vue-style-loader", "css-loader"]
}
import './assets/css/style.css'

vue-style-loader 是 vue-loader 的 dependencies,因此不需要再自己安装,css-loader 是 vue-loader 的 peerDependencies,需要自己安装。

支持 CSS 预处理语言

根据需要安装预处理语言模块及对应的 loader。

# less
npm install less less-loader -D

# sass
npm install node-sass sass-loader -D

# stylus
npm install stylus stylus-loader -D

node-sass 安装慢的解决办法:

各种预处理语言的 loader 配置。

// less
{
    test: /\.less$/,
    use: ["vue-style-loader", "css-loader", "less-loader"]
}

// sass
{
    test: /\.s[ac]ss$/,
    use: ["vue-style-loader", "css-loader", "sass-loader"]
}

// stylus
{
    test: /\.styl$/,
    use: ["vue-style-loader", "css-loader", "stylus-loader"]
}

使用示例。

<style lang="less">
.view{
    color:red;
}
</style>

<style lang="sass">
.view{
    border-bottom:1px solid #ddd;
}
</style>

<style lang="styl">
.view
    margin-top:20px;
</style>

支持图片及图标字体

安装图片及图标字体依赖的 loader。

npm install url-loader file-loader -D

配置图片及图标字体对应的 loader。

{
    test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
    use: [{
        loader: "url-loader",
        options: {
            limit: 10000,
            name: 'images/[name].[hash:7].[ext]'    // 将图片都放入 images 文件夹下,[hash:7]防缓存
        }
    }]
},
{
    test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
    use: [{
        loader: "url-loader",
        options: {
            limit: 10000,
            name: 'fonts/[name].[hash:7].[ext]'    // 将字体放入 fonts 文件夹下
        }
    }]
}

构建

使用 Webpack CLI 提供的命令构建。点击查看 Webpack 命令参数

"build": "webpack --progress"

执行npm run build开始构建,完成后,可以看到工程目录下多了 dist 目录,里面包含了打包后的 JavaScript 文件、图片、图标字体文件,但是打包后的 JavaScript 文件没有被压缩,里面还包含了 CSS 代码,语法也没有被转换成 ES5,这些工作就需要使用 Webpack 插件来完成。

使用 Webpack 插件

Babel

Babel 7 正式版已经发布,较 Babel 6 变化如下:

安装 Babel。

npm install babel-loader @babel/core @babel/cli @babel/preset-env -D

增加 Babel 配置文件 babel.config.js。

const presets = [
    ["@babel/env", {
        targets: {
            ie: "9"
        },
        modules: false
    }]
]

module.exports = {
    presets
}

配置 babel-loader。

{
    test: /\.js$/,
    exclude: /node_modules/,
    use: ["babel-loader"]
}

压缩

上面提到过, Webpack 4 新增的 mode 配置项配置为'production'时,已经包含了压缩插件(new UglifyJsPlugin()),因此不用再额外配置。

提取 CSS

extract-text-webpack-plugin 不支持 Webpack 4,提取 CSS 改用 mini-css-extract-plugin

npm i mini-css-extract-plugin -D

调整 Webpack 配置如下。

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
    //...
    module: {
        rules: [{
                test: /\.css$/,
                use: [MiniCssExtractPlugin.loader, "css-loader"]
            }, {
                test: /\.less$/,
                use: [MiniCssExtractPlugin.loader, "css-loader", "less-loader"]
            }, {
                test: /\.s[ac]ss$/,
                use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"]
            }, {
                test: /\.styl$/,
                use: [MiniCssExtractPlugin.loader, "css-loader", "stylus-loader"]
            }
            //...
        ]
    },
    plugins: [
        // ...
        new MiniCssExtractPlugin({
            filename: 'css/style.css'
        })
    ]
}

vue-loader 不需要单独配置就可以提取 vue 文件中的 CSS。在 index.html 中引入 CSS 文件即可看到效果。

CSS 压缩及优化

安装 postcss-loader 及 PostCSS 插件。

npm install postcss-loader autoprefixer cssnano -D

loader 配置调整如下。

{
    test: /\.css$/,
    use: [MiniCssExtractPlugin.loader, "css-loader", 'postcss-loader']
}, {
    test: /\.less$/,
    use: [MiniCssExtractPlugin.loader, "css-loader", 'postcss-loader', "less-loader"]
}, {
    test: /\.s[ac]ss$/,
    use: [MiniCssExtractPlugin.loader, "css-loader", 'postcss-loader', "sass-loader"]
}, {
    test: /\.styl$/,
    use: [MiniCssExtractPlugin.loader, "css-loader", 'postcss-loader', "stylus-loader"]
}

postcss-loader 要放在 css-loader 后,CSS 预处理语言的 loader 之前。

新增 postcss-loader 需要配置文件 postcss.config.js,引入插件。

module.exports = {
    plugins: [
        require('autoprefixer')({
            browsers: ['android > 4']
        }),
        require('cssnano')
    ]
}

PostCSS 插件分类搜索网站:http://postcss.parts/

生成首页

手动引入打包后的 JavaScript 和 CSS 比较麻烦,使用 html-webpack-plugin 插件生成的页面自动引入了打包后的资源。

npm install html-webpack-plugin -D

初始化插件。

var HtmlWebpackPlugin = require('html-webpack-plugin')

plugins: [
    new HtmlWebpackPlugin({
        filename: 'index.html',
        template: 'index.tpl.html'
    })
]

index.tpl.html

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

分离 Webpack 配置

将开发和生产配置文件分离,方便增加各个环境下的个性配置。Webpack 官方文档中也详细阐述了如何为多环境增加配置文件,基本思路如下。

webpack.base.config.js 内容如下。

const VueLoaderPlugin = require('vue-loader/lib/plugin')
module.exports = {
    entry: './src/main.js',
    output: {
        filename: 'js/[name].js'
    },
    module: {
        rules: [{
                test: /\.vue$/,
                use: ["vue-loader"]
            }, {
                test: /\.js$/,
                exclude: /node_modules/,
                use: ["babel-loader"]
            }, {
                test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
                use: [{
                    loader: "url-loader",
                    options: {
                        limit: 10000,
                        name: 'images/[name].[hash:7].[ext]' // 将图片都放入 images 文件夹下,[hash:7]防缓存
                    }
                }]
            },
            {
                test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
                use: [{
                    loader: "url-loader",
                    options: {
                        limit: 10000,
                        name: 'fonts/[name].[hash:7].[ext]' // 将字体放入 fonts 文件夹下
                    }
                }]
            }
        ]
    },
    plugins: [
        new VueLoaderPlugin()
    ]
}

开发环境一般不配置提取 CSS,而生产环境需要配置,因此上面的基础配置不包含 CSS loader。path 和 publicPath 在开发和生产环境下一般不同,因此也不包含在基础配置中。

开发配置文件(webpack.dev.config.js)内容如下内容如下。

const merge = require("webpack-merge")
const HtmlWebpackPlugin = require("html-webpack-plugin")
const baseWebpackConfig = require("./webpack.base.config")
module.exports = merge(baseWebpackConfig, {
    mode: 'development',
    output: {
        publicPath: "/"
    },
    module: {
        rules: [{
            test: /\.css$/,
            use: ["vue-style-loader", "css-loader", 'postcss-loader']
        }, {
            test: /\.less$/,
            use: ["vue-style-loader", "css-loader", 'postcss-loader', "less-loader"]
        }, {
            test: /\.s[ac]ss$/,
            use: ["vue-style-loader", "css-loader", 'postcss-loader', "sass-loader"]
        }, {
            test: /\.styl$/,
            use: ["vue-style-loader", "css-loader", 'postcss-loader', "stylus-loader"]
        }]
    },
    plugins: [
        new HtmlWebpackPlugin({
            filename: "index.html",
            template: "index.tpl.html"
        })
    ]
})

生产配置文件(webpack.prod.config.js)内容如下。

const merge = require("webpack-merge")
const HtmlWebpackPlugin = require("html-webpack-plugin")
const MiniCssExtractPlugin = require("mini-css-extract-plugin")
const baseWebpackConfig = require("./webpack.base.config")
const path = require('path')
module.exports = merge(baseWebpackConfig, {
    mode: 'production',
    output: {
        path: path.resolve(__dirname, '../dist')
        publicPath: "/static/"
    },
    module: {
        rules: [{
            test: /\.css$/,
            use: [MiniCssExtractPlugin.loader, "css-loader", 'postcss-loader']
        }, {
            test: /\.less$/,
            use: [MiniCssExtractPlugin.loader, "css-loader", 'postcss-loader', "less-loader"]
        }, {
            test: /\.s[ac]ss$/,
            use: [MiniCssExtractPlugin.loader, "css-loader", 'postcss-loader', "sass-loader"]
        }, {
            test: /\.styl$/,
            use: [MiniCssExtractPlugin.loader, "css-loader", 'postcss-loader', "stylus-loader"]
        }]
    },
    plugins: [
        new MiniCssExtractPlugin({
            filename: 'css/style.css'
        }),
        new HtmlWebpackPlugin({
            filename: "index.html",
            template: "index.tpl.html"
        })
    ]
})

对应在 package.json 中添加开发和生产构建的命令如下。

"scripts": {
    "dev": "webpack-dev-server --progress --hot --open --config build/webpack.dev.config.js",
    "build": "webpack --progress --config build/webpack.prod.config.js",
}
原创文章,持续完善中,转载请注明出处。本文地址: https://www.qinshenxue.com/article/vue2-vue-router2-webpack4.html
Star支持 评论