webpack 4.x 从零开始初始化一个vue项目

创建目录

项目名称: vue-init
app
├─css
│ reset.scss

├─js
│ │ App.vue
│ │ main.js
│ │
│ ├─home
│ │ index.vue
│ │
│ └─router
│ index.js

└─views
index.html

安装webpack

npm i -D webpack

创建配置文件

webpack.config.js
基础配置

  • entry 入口
  • module 模块
  • plugins 插件
  • output 输出

进阶配置

  • resolve
  • devtool
  • devServer
  • ...

基础配置

步骤

先写好基本结构

module.exports = {
    enter: {},
    module: {},
    plugins: [],
    output: {}
}

配置入口文件,以main.js作为打包入口文件

    enter: {
        app: './app/js/main.js'
    }

配置module,里面主要配置使用的各种loader

   module: {
        rules: [
            {
                test: /\.html$/,
                use: [
                    {
                        loader: 'html-loader'
                    }
                ]
            },
            {
                test: /\.vue$/,
                use: [
                    {
                        loader: 'vue-loader'
                    }
                ]
            },
            {
                test: /\.scss$/,
                use: [
                    { loader: 'style-loader' },
                    {
                        loader: 'css-loader',
                        options: {
                            module: true
                        }
                    },
                    { loader: 'sass-loader' },
                ]
            },
        ]
    },
  • test 的值为正册表达式,配对文件后缀,表示什么文件对应的loader
  • sass 需要使用多个loader,解析顺序是从右向左
  • options: { module: true } 开启css module

稍后再配置plugins,先配置output

//在webpack.config.js顶部引入path
const path = require('path');
    output: {
        filename: '[name].min.js',
        path: path.resolve(_dirname, 'dist')
    }
}
  • filename表示打包后输出的文件名
  • [name] 对应 enter.app的值
  • path 打包输出的路径
  • path.resolve() webpack的执行环境是node,这里的path是node里的一个对象,用于处理文件路径和目录路径

配置好了 我们开始安装loaders

npm i -D html-loader vue-loader style-loader css-loader sass-loader

如果有loader安装不成功请再单个安装它,或者换用cnpm

基础配置代码

到这一步我们的基础配置已经做好,代码如下:

module.exports = {
    enter: {
        app: './app/js/main.js'
    },
    module: {
        rules: [
            {
                test: /\.html$/,
                use: [
                    {
                        loader: 'html-loader'
                    }
                ]
            },
            {
                test: /\.vue$/,
                use: [
                    {
                        loader: 'vue-loader'
                    }
                ]
            },
            {
                test: /\.scss$/,
                use: [
                    { loader: 'style-loader' },
                    {
                        loader: 'css-loader',
                        options: {
                            module: true
                        }
                    },
                    { loader: 'sass-loader' },
                ]
            },
        ]
    },
    plugins: [],
    output: {
        filename: '[name].min.js',
        path: path.resolve(_dirname, 'dist')
    }
}

进阶配置

devServer

  devServer: {
    contentBase: path.join(__dirname, 'dist'),
    compress: true,
    port: 9000
  }
  • contentBase 告诉服务器从哪个目录中提供内容。
  • compress 压缩
  • port 启动端口号

配置好了 我们开始安装它

npm i -D webpack-dev-server

测试

添加一些代码以供测试
home/index.vue

<template>
    <div id="home">
        <h1>首页</h1>
        <p>123123<p>
    </div>
</template>

<script>
export default {}
</script>

<style lang="scss" scoped>
    .home {
        color: red;
        font-size: 80px;
        p {
            color: blue
        }
    }
</style>

router/index.js

import Vue from "vue"
import Router from "vue-router"
import Home from "../home/index.vue"

Vue.use(Router);

export default new Router({
    routes: [{
        path: '/',
        name: 'home',
        component: Home
    }]
})

App.vue

<template>
  <div id="app">
    <router-view></router-view>
  </div>
</template>

<script>
export default {
    name: 'app'
};
</script>

<style lang="scss" scoped>
</style>

main.js

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

Vue.config.productionTip = false;

new Vue({
    router,
    render: h => h(App)
}).$mount("#app")

我们还需要安装 vue 和vue router

npm i vue vue-router

运行devServer

还需要安装两个依赖

npm i -D html-webpack-plugin clean-webpack-plugin

webpack.config.js顶部加入如下代码

    const HtmlWebpackPlugin = require('html-webpack-plugin');
    const { CleanWebpackPlugin } = require('clean-webpack-plugin');
    // 注意这里的写法, 这样写 const CleanWebpackPlugin 会报错
  • html-webpack-plugin

    官网文档解释:HtmlWebpackPlugin简化了HTML文件的创建,以便为你的webpack包提供服务。这对于在文件名中包含每次会随着编译而发生变化哈希的 webpack bundle 尤其有用。 你可以让插件为你生成一个HTML文件,使用lodash模板提供你自己的模板,或使用你自己的loader。另外你可以在github查看这个项目的详细配置。

  • clean-webpack-plugin 在每次构建前清理 /dist 文件夹,这样只会生成用到的文件。

配置plugins

    plugins: [
        new CleanWebpackPlugin(),
        new HtmlWebpackPlugin({
            template: './views/index.html'
        })
    ],

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>
</body>
</html>

package.json 加入 "start": "webpack-dev-server --open"

  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "webpack-dev-server --open"
  },

跑完发现一大堆报错

  • You may need an additional loader to handle the result of these loaders. Vue-loader在15.*之后的版本都是 vue-loader的使用都是需要伴生 VueLoaderPlugin的
npm i vue-loader-plugin -S

webpack.config.js

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

module.exports = {
  // ...
  plugins: [
    new VueLoaderPlugin()
  ]
}
  • Cannot find module 'node-sass'
    安装就完了,最后我们npm start 项目成功运行

px2rem

npm install -D px2rem-loader
module: {
        rules: [
            {
                test: /\.html$/,
                use: 'html-loader'
            },
            {
                test: /\.vue$/,
                use: 'vue-loader'
            },
            {
                test: /\.scss$/,
                use: [
                    'vue-style-loader',
                    'css-loader',
                    {
                        loader: 'px2rem-loader',
                        options: {
                            remUnit: 75,
                            remPrecision: 6
                        }
                    },
                    'sass-loader'
                ]
            },
        ]
    },

这部分为什么这么配置,参考了Vue官方文档 -> 单文件组建 -> 针对高级用户 -> VueLoader
原来的webpack3.x需要在vue-loader 下配置css 和 sass 并配置 px2rem。

css module

// ...
{
    test: /\.scss$/,
    use: [
        'vue-style-loader',
+        {
+            loader: 'css-loader',
+             options: {
+                 modules: true,
+                 localIdentName: '[local]_[hash:base64:8]'
+             }
+        },
        {
            loader: 'px2rem-loader',
            options: {
                remUnit: 75,
                remPrecision: 6
            }
        },
        'sass-loader'
    ]
},

如果你不知道如何使用css module 请参阅Vue官方文档 -> 单文件组建 -> 针对高级用户 -> VueLoader -> css module

css提取

npm install -D mini-css-extract-plugin
{
    test: /\.scss$/,
    use: [
        MiniCssExtractPlugin.loader,
        {
            loader: 'css-loader',
            options: {
                modules: true
            }
        },
        {
            loader: 'px2rem-loader',
            options: {
                remUnit: 75,
                remPrecision: 6
            }
        },
        'sass-loader'
    ]
},
plugins: [
    // ...
    new MiniCssExtractPlugin({
      filename: 'style.css'
    })
  ]

区分生产环境和开发环境

webpack3

我们需要使用webpack的DefinePlugin创建一个在编译时可以配置的全局常量。在webpack.config.js头部引入webpack

const webpack = require('webpack');

接下来我们把module.exports的值改为箭头函数,并传入一个参数env

module.exports = env => {
    if (!env) { env = {} }
    return {
        // 原来的配置
    }
}

我们先来做一个示例,例如我们在开发环境不需要css提取

module.exports = env => {
    if (!env) { env = {} }

    let plugins = [
        new CleanWebpackPlugin(),
        new HtmlWebpackPlugin({
            template: './views/index.html'
        }),
        new VueLoaderPlugin(),
    ];

    if (env.production) {
        plugins.push(
            new webpack.DefinePlugin({
                'process.env': {
                    NODE_ENV: 'production'
                }
            }),
            new MiniCssExtractPlugin({
                filename: 'style.css'
            })
        )
    }
  • process 对象是属于node的一个全局变量
  • 我们只需要根据是否传入了env.production,然后给plugins数组push生产环境下需要的MiniCssExtractPlugin插件

对应的我们还有修改部分原来的代码

{
    test: /\.scss$/,
    use: [
*       env.production?MiniCssExtractPlugin.loader:'vue-style-loader',
        {
            loader: 'css-loader',
            options: {
                modules: true
            }
        },
        {
            loader: 'px2rem-loader',
            options: {
                remUnit: 75,
                remPrecision: 6
            }
        },
        'sass-loader'
    ]
},

以及原来的plugins配置我们直接将它的值变为我们上面定义的plugins。
package.json中我们需要添加命令

  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "webpack-dev-server --open",
    "watch": "webpack --watch",
    "build" : "webpack --env.production"
  },

注意我们给webpack 传递了参数,我们就是利用这个参数来区分环境。

npm start


控制台我们可以看到
css样式以style标签插入,并没有被提取,说明MiniCssExtractPlugin插件没有运行

npm run build

运行打包后的index.html,css样式以link标签插入,说明css被提取合并为一个文件,说明生产环境下MiniCssExtractPlugin插件运行了

webpack4

上面是的做法看起来更好理解,webpack4中我们可以直接利用mode来区分开发环境和生产环境。头部我们不需要引入webpack了, 因为我们不需要依赖 DefinePlugin。
配置中新增:

mode: 'development' //默认是 development
module.exports = (env, argv) => {
  if (argv.mode === 'production') {
    //...
  }

  return config;
};

eslint

npm i eslint -D

eslint支持多种格式的配置文件,同时支持把配置直接写在package.json中,我们直接在写在package.json中,如何配置呢?
vue项目可以直接使用vue官方推荐的插件

npm i eslint-plugin-vue -D

package.json添加如下:

{
  // 其他配置
 "eslintConfig": {
    "root": true,
    "parserOptions": {
      "ecmaVersion": 2017
    },
    "extends": [
      "mysticatea",
      "mysticatea/modules",
      "plugin:vue/recommended"
    ],
    "plugins": [
      "node"
    ],
    "env": {
      "browser": false
    },
    "globals": {
      "applicationCache": false,
      "atob": false,
      "btoa": false,
      "console": false,
      "document": false,
      "location": false,
      "window": false
    },
    "rules": {
      "node/no-extraneous-import": "error",
      "node/no-missing-import": "error",
      "node/no-unpublished-import": "error",
      "vue/html-indent": [
        "error",
        4
      ],
      "vue/max-attributes-per-line": "off"
    }
  },
  "eslintIgnore": [
    "node_modules",
    "webpack.config.js"
  ]
}
posted @ 2019-12-08 15:53  DIV狂魔  阅读(...)  评论(...编辑  收藏