初探webpack之搭建Vue开发环境

24 篇文章 0 订阅
11 篇文章 0 订阅

描述

平时我们可以用vue-cli很方便地搭建Vue的开发环境,vue-cli确实是个好东西,让我们不需要关心webpack等一些繁杂的配置,然后直接开始写业务代码,但这会造成我们过度依赖vue-cli,忽视了webpack的重要性,当遇到一些特殊场景时候,例如Vue多入口的配置、优化项目的打包速度等等时可能会无从下手。

实现

搭建环境

初探webpack,那么便从搭建简单的webpack环境开始,首先是初始化并安装依赖。

$ yarn init -y
$ yarn add -D webpack webpack-cli cross-env

首先可以尝试一下webpack打包程序,webpack可以零配置进行打包,目录结构如下:

webpack-simple
├── package.json
├── src
│   ├── index.js
│   └── sum.js
└── yarn.lock
// src/sum.js
export const add = (a, b) => a + b;
// src/index.js
import { add } from "./sum";
console.log(add(1, 1));

之后写入一个打包的命令。

// package.json
{
    // ...
    "scripts": {
        "build": "webpack"
    },
    // ...
}

执行npm run build,默认会调用node_modules/.bin下的webpack命令,内部会调用webpack-cli解析用户参数进行打包,默认会以src/index.js作为入口文件。

$ npm run build

执行完成后,会出现警告,这里还提示我们默认modeproduction,此时可以看到出现了dist文件夹,此目录为最终打包出的结果,并且内部存在一个main.js,其中webpack会进行一些语法分析与优化,可以看到打包完成的结构是。

// src/main.js
(()=>{"use strict";console.log(2)})();

webpack配置文件

当然我们打包时一般不会采用零配置,此时我们就首先新建一个文件webpack.config.js。既然webpack说默认modeproduction,那就先进行一下配置解决这个问题,因为只是一个简单的webpack环境我们就不区分webpack.dev.jswebpack.prod.js进行配置了,简单的使用process.env.NODE_ENVwebpack.config.js中区分一下即可,cross-env是用以配置环境变量的插件。

// package.json
{
    // ...
    "scripts": {
        "build": "cross-env NODE_ENV=production webpack --config webpack.config.js"
    },
    // ...
}
const path = require("path");
module.exports = {
    mode: process.env.NODE_ENV,
    entry: "./src/index.js",
    output: {
        filename: "index.js",
        path:path.resolve(__dirname, "dist")
    }
}

HtmlWebpackPlugin插件

我们不光是需要处理js文件的,还需要处理html文件,这里就需要使用html-webpack-plugin插件。

$ yarn add -D html-webpack-plugin

之后在webpack.config.js中进行配置,简单配置一下相关的输入输出和压缩信息,另外如果要是想每次打包删除dist文件夹的话可以考虑使用clean-webpack-plugin插件。

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

module.exports = {
    mode: process.env.NODE_ENV,
    entry: "./src/index.js",
    output: {
        filename: "index.js",
        path:path.resolve(__dirname, "dist")
    },
    plugins:[
        new HtmlWebpackPlugin({
            title: "Webpack Template", 
            filename: "index.html", // 打包出来的文件名 根路径是`module.exports.output.path`
            template: path.resolve("./public/index.html"),
            hash: true, // 在引用资源的后面增加`hash`戳
            minify: {
                collapseWhitespace: true,
                removeAttributeQuotes: true,
                minifyCSS: true,
                minifyJS: true,
            },
            inject: "body", // `head`、`body`、`true`、`false`
            scriptLoading: "blocking" // `blocking`、`defer`
        })
    ]
}

之后新建/public/index.html文件,输入将要被注入的html代码。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <title><%= htmlWebpackPlugin.options.title %></title>
  </head>
  <body>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>

启动npm run build,我们就可以在/dist/index.html文件中看到注入成功的代码了。

<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><title>Webpack Template</title></head><body><div id=app></div><!-- built files will be auto injected --><script src=index.js?94210d2fc63940b37c8d></script></body></html>

webpack-dev-server

平时开发项目,预览效果时,一般直接访问某个ip和端口进行调试的,webpack-dev-server就是用来帮我们实现这个功能,他实际上是基于express来实现web服务器的功能,另外webpack-dev-server打包之后的htmlbundle.js是放在内存中的,目录里是看不到的,一般会配合webpack的热更新来使用。

$ yarn add -D webpack-dev-server

接下来要在webpack.config.js配置devServer环境,包括package.json的配置。

// webpack.config.js

// ...
module.exports = {
    // ...
    devServer: {
        hot: true, // 开启热更新
        open: true, // 自动打开浏览器预览
        compress: true, // 开启gzip
        port: 3000  //不指定端口会自动分配
    },
    // ...
}
// package.json
// ...
"scripts": {
    "build": "cross-env NODE_ENV=production webpack --config webpack.config.js",
    "dev": "cross-env NODE_ENV=development webpack-dev-server --config webpack.config.js"
},
// ...

搭建Vue基础环境 


首先我们可以尝试一下对于.js中编写的Vue组件进行构建,即不考虑单文件组件.vue文件的加载,只是构建一个Vue对象的实例,为了保持演示的代码尽量完整,此时我们在src下建立一个main.js出来作为之后编写代码的主入口,当然我们还需要在index.js中引入main.js。

首先我们需要安装Vue,之后才能使用Vue进行开发。

$ yarn add vue

之后在/src/main.js中编写如下内容。

// /src/main.js
import Vue from "vue";

new Vue({
    el: "#app",
    template: "<div>Vue Example</div>"
})

之后我们正式开始处理.vue文件,首先新建一个App.vue文件在根目录,此时的目录结构如下所示。

webpack-simple-environment
├── dist
│   ├── index.html
│   └── index.js
├── public
│   └── index.html
├── src
│   ├── App.vue
│   ├── index.js
│   ├── main.js
│   └── sum.js
├── jsconfig.js
├── LICENSE
├── package.json
├── README.md
├── webpack.config.js
└── yarn.lock

 之后我们修改一下main.js以及App.vue这两个文件。

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

const app = new Vue({
    ...App,
});
app.$mount("#app");
<!-- App.vue -->
<template>
    <div class="example">{{ msg }}</div>
</template>

<script>
export default {
    name: "App",
    data: () => ({
        msg: "Example"
    })
}
</script>

<style scoped>
    .example{
        font-size: 30px;
    }
</style>

之后便是使用loader进行处理的环节了,因为我们此时需要对.vue文件进行处理,我们需要使用loader处理他们。

$ yarn add -D vue-loader vue-template-compiler css-loader vue-style-loader

 之后需要在webpack.config.js中编写相关配置,之后我们运行npm run dev就能够成功运行了。

// webpack.config.js

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

module.exports = {
    // ...
    module: {
        rules: [
            {
                test: /\.vue$/,
                use: "vue-loader",
            },
            {
                test: /\.css$/,
                use: [
                    "vue-style-loader",
                    "css-loader"
                ],
            },
        ],
    },
    plugins:[
        new VueLoaderPlugin(),
        // ...
    ]
}

处理资源文件

通常我们需要处理资源文件,同样是需要使用loader进行处理,主要是对于图片进行处理。

$ yarn add -D url-loader file-loader
// webpack.config.js

// ...
module.exports = {
    // ...
    module: {
        rules: [
            // ...
            {
                test: /\.(png|jpg|gif)$/i,
                use: [
                    {
                        loader: "url-loader",
                        options: {
                            esModule: false,
                            limit: 8192, //小于`8K`,用`url-loader`转成`base64` ,否则使用`file-loader`来处理文件
                            fallback: {
                                loader: "file-loader",
                                options: {
                                    esModule: false,
                                    name: "[name].[hash:8].[ext]",
                                    outputPath: "static", //打包之后文件存放的路径, dist/static
                                }
                            },
                        }
                    }
                ]
            },
            // ...
        ],
    },
    // ...
}
<!-- App.vue -->
<template>
    <div>
        <img src="./static/vue.jpg" alt="" class="vue">
        <img src="./static/vue-large.png" alt="" class="vue-large">
        <div class="example">{{ msg }}</div>
    </div>
</template>

<script>
export default {
    name: "App",
    data: () => ({
        msg: "Example"
    })
}
</script>

<style scoped>
    .vue{
        width: 100px;
    }
    .vue-large{
        width: 300px;
    }
    .example{
        font-size: 30px;
    }
</style>

之后运行npm run dev,就可以看到效果了,可以在控制台的Element中看到,小于8K的图片被直接转成了base64,而大于8K的文件被当作了外部资源进行引用了。

<!-- ... -->
<img data-v-7ba5bd90="" src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASA..." alt="" class="vue">
<img data-v-7ba5bd90="" src="http://localhost:3000/static/vue-large.b022422b.png" alt="" class="vue-large"> 
<!-- ... -->

处理Babel 

使用babel主要是为了做浏览器的兼容,@babel/corebabel核心包,@babel/preset-env是集成bebal一些可选方案,可以通过修改特定的参数来使用不同预设,babel-loader可以使得ES6+ES5babel默认只转换语法而不转换新的APIcore-js可以让不支持ES6+ API的浏览器支持新API,当然也可以用babel-polyfill,相关区别可以查阅一下,建议用core-js。

$ yarn add -D @babel/core @babel/preset-env babel-loader
$ yarn add core-js@3

之后在根目录新建一个babel.config.js,然后将以下代码写入。

// babel.config.js
module.exports = {
    "presets": [
        [
            "@babel/preset-env",
            {
                "useBuiltIns": "usage",
                "corejs": 3,
                "modules": false
            }
        ]
    ]
}

 之后修改一下App.vue,写一个较新的语法?.

<!-- App.vue -->
<template>
    <div>
        <img src="./static/vue.jpg" alt="" class="vue">
        <img src="./static/vue-large.png" alt="" class="vue-large">
        <div class="example">{{ msg }}</div>
        <button @click="toast">按钮</button>
    </div>
</template>

<script>
export default {
    name: "App",
    data: () => ({
        msg: "Example"
    }),
    methods: {
        toast: function(){
            window?.alert("ExampleMessage");
        }
    }
}
</script>

<style scoped>
    .vue{
        width: 100px;
    }
    .vue-large{
        width: 300px;
    }
    .example{
        font-size: 30px;
    }
</style>

还需要修改一下webpack.config.js

// webpack.config.js

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

 处理Css

通常我们一般不只写原生css,我一般使用sass这个css框架,所以此处需要安装sass以及sass-loadersass-loader请使用低于@11.0.0的版本,sass-loader@11.0.0不支持vue@2.6.14,此外我们通常还需要处理CSS不同浏览器兼容性,所以此处需要安装postcss-loader,当然postcss.config.js也是可以通过postcss.config.js文件配置一些信息的,比如@/别名等,另外需要注意,在use中使用loader的解析顺序是由下而上的,例如下边的对于scss文件的解析,是先使用sass-loader再使用postcss-loader。

yarn add -D sass sass-loader@10.1.1 postcss postcss-loader 

之后简单写一个示例,新建文件/src/common/styles.scss,然后其中写一个变量$color-blue: #4C98F7;

$color-blue: #4C98F7;

之后修改App.vuewebpack.config.js,然后运行npm run dev就可以看到Example这个文字变成了蓝色。 

<!-- App.vue -->
<template>
    <div>
        <img src="./static/vue.jpg" alt="" class="vue">
        <img src="./static/vue-large.png" alt="" class="vue-large">
        <div class="example">{{ msg }}</div>
        <button @click="toast">按钮</button>
    </div>
</template>

<script>
export default {
    name: "App",
    data: () => ({
        msg: "Example"
    }),
    methods: {
        toast: function(){
            window?.alert("ExampleMessage");
        }
    }
}
</script>

<style scoped lang="scss">
    @import "./common/styles.scss";
    .vue{
        width: 100px;
    }
    .vue-large{
        width: 300px;
    }
    .example{
        color: $color-blue;
        font-size: 30px;
    }
</style>
// webpack.config.js

// ...
module.exports = {
    // ...
    module: {
        rules: [
            // ...
            {
                test: /\.css$/,
                use: [
                    "vue-style-loader",
                    "css-loader",
                    "postcss-loader"
                ],
            },
            {
                test: /\.(scss)$/,
                use: [
                    "vue-style-loader",
                    "css-loader",
                    "postcss-loader",
                    "sass-loader",
                ]
            },
            // ...
        ],
    },
    // ...
}

 配置ESLint

$ yarn add -D eslint eslint-config-prettier eslint-plugin-prettier eslint-plugin-vue prettier vue-eslint-parser

根目录下建立.editorconfig.eslintrc.js.prettierrc.js,进行一些配置,当然这都是可以自定义的,不过要注意prettiereslint规则冲突的问题。

<!-- .editorconfig -->
root = true

[*]
charset = utf-8
indent_style = space
indent_size = 4
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
// .prettierrc.js
module.exports = {
    "printWidth": 100, // 指定代码长度,超出换行
    "tabWidth": 4, // tab 键的宽度
    "useTabs": false, // 不使用tab
    "semi": true, // 结尾加上分号
    "singleQuote": false, // 使用单引号
    "quoteProps": "preserve", // 不要求对象字面量属性是否使用引号包裹
    "jsxSingleQuote": false, // jsx 语法中使用单引号
    "trailingComma": "es5", // 确保对象的最后一个属性后有逗号
    "bracketSpacing": true, // 大括号有空格 { name: 'rose' }
    "jsxBracketSameLine": false, // 在多行JSX元素的最后一行追加 >
    "arrowParens": "avoid", // 箭头函数,单个参数不强制添加括号
    "requirePragma": false, // 是否严格按照文件顶部的特殊注释格式化代码
    "insertPragma": false, // 是否在格式化的文件顶部插入Pragma标记,以表明该文件被prettier格式化过了
    "proseWrap": "preserve", // 按照文件原样折行
    "htmlWhitespaceSensitivity": "ignore", // html文件的空格敏感度,控制空格是否影响布局
    "endOfLine": "lf" // 结尾是 \n \r \n\r auto
}

我们还可以配置一下lint-staged,在ESLint检查有错误自动修复,无法修复则无法执行git add

$ yarn add -D lint-staged husky
$ npx husky install
$ npx husky add .husky/pre-commit "npx lint-staged"
// package.json
{
  // ...
  "lint-staged": {
    "*.{js,vue,ts}": [  "eslint --fix" ]
  }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值