小白学习手动搭建vue架构(webpack4)

335 阅读6分钟

1、初始化项目

npm init -y

2、安装webpack4、webpack-cli

npm i webpack@4 webpack-cli -D

3、webpack4配置

安装完webpack和webpack-cli之后,在项目根目录下创建webpack.config.js文件,创建以下内容:

const path = require("path");
const webpack = require("webpack");
const htmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
    entry: path.resolve(__dirname, './src/main.js'), // 项目的入口文件
    output: {
        path: path.resolve(__dirname, './dist'), // 打包之后文件的存储目录dist
        filename: './static/bundle-[hash:8].js', // hash:8 意为添加8位哈希码,文件目录为dist/static
        publicPath: '/'
    }
}

4、配置webpack4打包命令

在package.json中的scripts里配置对应的webpack命令:

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

5、创建入口文件

根目录下新建src目录,在src目录下新建main.js文件,作为整个项目的入口文件。这个入口文件在webpack.config.js的entry属性中配置好了。

6、打包项目

打开终端输入npm run build,执行完成后,会在根目录下生成打包后的文件dist,打开dist目录,可以看到在webpack.config.js中配置的输出文件bundle.js。至此,已经简单的创建了一个基于webpack的项目。接下来需要先将项目能够跑起来。

7、创建模板文件

在项目根目录下创建index.html, 如下:

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <!-- <meta name="viewport" content="width=device-width,initial-scale=1.0"> -->
  <!-- 控制不缓存 -->
  <meta http-equiv="Expires" content="0">
  <meta http-equiv="Pragma" content="no-cache">
  <meta http-equiv="Cache-control" content="no-cache">
  <meta http-equiv="Cache" content="no-cache">
  <link rel="shortcut icon" href="" type="image/x-icon">
  <title>demo</title>
  <style>
    body, html {
      margin: 0;
      padding: 0;
    }
  </style>
</head>

<body>
  <div id="app"></div>
  <!-- built files will be auto injected -->
</body>

</html>

8、安装html-webpack-plugin

html-webpack-plugin可以在项目运行的时候,依照项目的index.html自动生成打包后的index.html(引入各个js和css)。如下:

npm i html-webpack-plugin@4 -D

9、配置webpack

安装好html-webpack-plugin之后,要想自动生成打包后对应的index.html,还需要在webpack.config.js中实现html-webpack-plugin的实例,以项目根目录下的index.html为模板,自动生成可运行的index.html。在webpack.config.js加入如下代码

const htmlWebpackPlugin = require('html-webpack-plugin') // 引入html-webpack-plugin
// 在plguins数组中加入
plugins: [
     new htmlWebpackPlugin({
        // 可以指定文件当模板  让这个文件为入口  读取模板的入口文件
        template: path.resolve(__dirname, '../index.html'),
        // 输出的模板文件,名为index.html, 在dist目录下
        filename: 'index.html'
     })
]

保存再次执行npm run build,可以在对应的dist目录下看到index.html文件,浏览器打开index.html。但这样需要每次先手动打包,然后再打开访问。可以通过安装webpack-dev-server,实现打包自动运行。

10、安装webpack-dev-server

webpack-dev-server是前端开发服务器。webpack-dev-server特点:

  • 令Webpack进行模块打包,并处理打包结果的资源请求
  • 作为普通的Web Server,处理静态资源文件请求
  • 解决了来回npm run build,再更新代码的问题,比较便捷
  • 可以设置port端口和open(自动打开页面),其他更多配置可以参考官网api
  • 自动刷新:浏览器自动更改后的内容
npm i webpack-dev-server -D

安装后,需要配置webpack.config.js,如下:

devServer: {
    contentBase: path.resolve(__dirname, '../dist'), // 将dist目录下的文件serve到localhost:8888下
    compress: true, // 是否压缩
    open: true, // 自动打开浏览器
    host: 'localhost', // 本地访问地址
    port: 8888,  // 本地访问的端口
    hot: true, //启用webpack的热模块替换功能
    historyApiFallback: true, // 不跳转
    inline: true, // 实时刷新,
    overlay: {
        warning: true,
        errors: true
    },
    publicPath: '/' // 文件访问的默认目录为根目录,可以指定
},

配置完成后,需要配置package.json的开发服务器启动命令:

"scripts": {
    "dev": "webpack server --config ./webpack.config.js"
}

这边有一个警告,让我们设置mode,它会有默认值,也可以通过scripts命令传递,通过node的process.env获取。如下:

"scripts": {
    "dev": "webpack server --mode=development --config ./webpack.config.js"
}

这样就可以使用npm run dev来启动开发服务器运行项目了。

11、安装clean-webpack-plugin

每次打包的时候,发现总是要先删除原来的包,不然的话,会增大dist包。可以通过clean-webpack-plugin插件实现每次打包前删除原来的dist。clean-webpack-plugin默认删除的是output配置的path的目录下的所有文件。

npm i clean-webpack-plugin -D

安装完成后,配置webpack.config.js,添加如下代码:

const { CleanWebpackPlugin } = require('clean-webpack-plugin') // 引入插件
plugins: [
    new CleanWebpackPlugin() // 实现实例
]

12、安装babel相关插件,安装vue-loader、url-loader、file-loader、style-loader、css-loader、sass-loader、node-sass、autoprefixer、postcss-loader、vue-template-compiler

12.1、安装babel相关插件,并配置.babelrc文件

在使用vue之前,需要先安装babel相关插件,是因为当前浏览器不支持es5以上标准的语法,需要使用babel将高级语法编译成当前浏览器能够执行的语法。webpack需要安装的是@babel/core@7、babel-loader@8以上。@babel/plugin-transform-runtime、@babel/preset-env、@babel/runtime、@babel/runtime-corejs2@babel/plugin-syntax-dynamic-import是对依赖进行动态引入的插件,babel-plugin-component是按需引入element-ui所需要的插件。core-js是完全模块化的javascript标准库。

npm i @babel/core@7 babel-loader@8 @babel/plugin-transform-runtime @babel/preset-env @babel/runtime @babel/runtime-corejs2 @babel/plugin-syntax-dynamic-import babel-plugin-component core-js@2 -D

安装完成之后,在项目根目录下创建.babelrc(新版本可以改成babel.config.js)文件,添加如下内容:

{
    "presets": [
        [
            "@babel/preset-env", {
                "useBuiltIns": "usage", //不需要把polyfill都打包到代码中,根据代码按需转译
                //"corejs": 3,  //npm i --save-dev core-js@3
                "corejs": 2,  //npm i --save-dev core-js@2
                "modules":false //关闭 Babel 的模块转换功能,保留原本的 ES6 模块化语法
                //默认是auto,取值还可以是 amd, umd, systemjs, commonjs,auto等
            }
        ]
    ],
    "plugins": [
        [
            "@babel/plugin-transform-runtime", {
                "helpers": true,
                "regenerator": true,
                "useESModules": true,
                "corejs": 2
            }
        ],
        "@babel/plugin-syntax-dynamic-import",
        [
            "component",
            {
              "libraryName": "element-ui",
              "styleLibraryName": "theme-chalk"
            }
          ]
    ]
 }

再在webpack.config.js添加如下代码:

module: {
    rules: [
        {
            test: /\.js|x$/,
            use: ['babel-loader'],
            exclude: /node_modules/ // 不编译node_modules下的代码
        }
    ]
}

12.2、安装vue-loader、vue-template-compiler

vue-loader是vue的转译器,只有装了它,项目才能识别vue文件并能进行转译。vue-template-compiler该模块可用于将 Vue 2.0 模板预编译为渲染函数(template => ast => render),以避免运行时编译开销和 CSP 限制。大都数场景下,与 vue-loader一起使用,只有在编写具有非常特定需求的构建工具时,才需要单独使用它, vue的版本必须与vue-template-compiler保持一致。

npm i vue-loader vue-template-compiler -D

安装完成之后,需要在webpack.config.js中进行配置。在module.exports对象中添加如下代码:

const VueLoaderPlugin = require('vue-loader/lib/plugin');
module: {
    rules: [
        {
            test: /\.vue$/,
            use: ['vue-loader']
        }
    ]
},
plugins: [
    new VueLoaderPlugin()
]

12.3、安装url-loader、file-loader

url-loader是用来处理图片、字体、媒体等类型文件的插件,不配置的话,项目打包运行后,将无法正确识别这些类型的资源。url-loader中包含了file-loader的部分功能,所以,如果对文件的限制没有到达限制,不需要单独配置file-loader。

npm i url-loader file-loader -D

安装完成后,需要在webpack.config.js中添加如下代码:

module: {
    rules: [
    {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        use: [{
            loader: 'url-loader',
            options: {
                esModule: false, // 这里设置为false, 不设置false,资源地址将会被编译成[object Module]
                limit: 10000,
                name: 'images/[name]-[hash:8].[ext]',  // 属于file-loader的属性
            }
        }]
    },
    {
        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
        use: [
            {
                loader: 'url-loader',
                options: {
                    esModule: false, // 这里设置为false
                    limit: 10000,
                    name: 'media/[name].[hash:7].[ext]'
                }
            }
        ]
    },
    {
        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
        loader: "url-loader",
        options: {
            esModule: false,                    // 这里设置为false
            limit: 10000,                        // size <= 5KB
            name: "fonts/[name]-[hash:7].min.[ext]",  // 属于file-loader的属性
        }
    }
    ]
}

12.4、安装style-loader、css-loader、sass-loader、node-sass、autoprefixer、postcss-loader

autoprefixer插件是用来在css代码前自动添加对应浏览器的前缀的。postcss-loader是用来把css解析为一个抽象语法树和调用插件处理抽象语法树并添加功能的。css-loader是用来解析代码里的css代码,style-loader是用来将css-loader解析好的代码挂载到html页面上的。node-sass是sass库,可以在项目的style便签里使用lang="scss"来使用sass语法,sass-loader是node-sass的编译器。由于项目中使用了element-ui,所以必须安装这两个插件

npm i style-loader css-loader sass-loader node-sass autoprefixer@9 postcss-loader@4 -D

安装完成后,在webpack.config.js中添加如下代码:

module: {
    rules: [
        {
            test: /\.(c|le)ss$/,
            use: [
                {
                    loader: 'style-loader'
                },
                {
                    loader: 'css-loader'
                },
                {
                    loader: 'postcss-loader',
                    options: {
                        sourceMap: true,
                        postcssOptions: {
                            plugins: [
                                [
                                    "autoprefixer",
                                    {
                                    // 选项
                                    },
                                ],
                            ]
                        }
                    }
                }
            ]
        }
    ]
}

至此,已经配置好了vue开发的所需的基本环境。接下来可以安装vue全家桶,配置好就可以进行开发了。

13、安装vue全家桶

vue全家桶包含vue、vue-router、vuex。详情请去查看vue官网。

npm i vue vue-router vuex -S

安装好之后,在项目根目录下新建views、router、store目录,各自目录下再新建index.js,编辑main.js:

import Vue from 'vue'
import App from './App.vue'
import Route from './router/index'
import Store from './store/index'

new Vue({
    el:"#app",
    router: Route,
    store: Store,
    render:(h)=>h(App)
})

在src目录下新建App.vue文件,添加如下代码:

<template>
  <div id="app">
    <router-view />
  </div>
</template>
<script>
export default {
  name: 'App'
}
</script>
<style scoped>
</style>

router目录下的index.js文件,添加如下代码:

import Vue from 'vue'
import Router from 'vue-router'

Vue.use(Router);

cosnt routes = []

const router = new Router({
    routes: routes
});

export default router;

store目录下的index.js文件,添加如下代码:

import Vue from 'vue'
import Vuex from 'vuex'

import user from './user/index'

Vue.use(Vuex);

const store = new Vuex.Store({
    modules: {
        user
    }
})

export default store

14、配置webpack.config.js

配置目录别名。配置扩展名,引入文件时不需要写文件扩展名。在webpack.config.js里添加如下代码:

module.exports = {
    ...
    resolve: {
        extensions: ['.js', '.vue', '.json'],//取消后缀  引入文件路径就不用加文件后缀了
        alias: {
            'vue$': 'vue/dist/vue.esm.js', //引入vue
            '@': path.resolve(__dirname,'../src')
        }
    }
    ...
}

15、安装element-ui

element-ui是饿了么的开源ui框架

npm i element-ui -S

最后附上完整的webpack.config.js文件

const path = require("path");
const webpack = require("webpack");
const htmlWebpackPlugin = require("html-webpack-plugin");
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const { CleanWebpackPlugin } = require("clean-webpack-plugin");

module.exports = {
    entry: path.resolve(__dirname, './src/main.js'),
    output: {
        path: path.resolve(__dirname, './dist'),
        filename: './static/bundle-[hash:8].js',
        publicPath: '/'
    },
    devServer: {
        open: true,
        hot: true,
        port: 8889
    },
    module: {
        rules: [
            {
                test: /\.js|x$/,
                use: ['babel-loader'],
                exclude: /node_modules/
            },
            {
                test: /\.vue$/,
                use: ['vue-loader']
            },
            {
                test: /\.c|(sc)ss$/,
                use: [
                    {
                        loader: 'style-loader'
                    },
                    {
                        loader: 'css-loader'
                    },
                    {
                        loader: 'sass-loader'
                    },
                    {
                        loader: 'postcss-loader',
                        options: {
                            sourceMap: true,
                            postcssOptions: {
                                plugins: [
                                    [
                                        "autoprefixer",
                                        {
                                        // 选项
                                        },
                                    ],
                                ]
                            }
                        }
                    }
                ]
            },
            {
                test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
                use: [{
                    loader: 'url-loader',
                    options: {
                        esModule: false, // 这里设置为false
                        limit: 10000,
                        name: 'images/[name]-[hash:8].[ext]',  // 属于file-loader的属性
                    }
                }]
            },
            {
                test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            esModule: false, // 这里设置为false
                            limit: 10000,
                            name: 'media/[name].[hash:7].[ext]'
                        }
                    }
                ]
            },
            {
                test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
                loader: "url-loader",
                options: {
                    esModule: false,                    // 这里设置为false
                    limit: 10000,                        // size <= 5KB
                    name: "fonts/[name]-[hash:7].min.[ext]",  // 属于file-loader的属性
                }
            }
        ],
    },
    plugins: [
        new htmlWebpackPlugin({
            template: path.resolve(__dirname, './index.html'),
            filename: path.resolve(__dirname, './dist/index.html')
        }),
        new CleanWebpackPlugin(),
        new VueLoaderPlugin()
    ]
}