基于 Webpack4 搭建 Vue 开发环境

自从工做以后,就已经好久没有写过博客了。时间被分割得比较碎,积累了一段时间的学习成果,才写下了这篇博客。css

以前有写过 Webpack4 的文章,可是都比较偏入门,惟一的一篇实战篇 —— 基于Webpack搭建React开发环境,也是比较简单的,没有涉及到 CSS 抽取,第三方库打包等功能,这篇文章相对而言比较深刻。但因为做者水平有限,不免存在谬误之处,欢迎你们指正。html

还有没入门的童鞋能够参考我以前的文章:vue

1、初始化项目

在命令行中敲入以下命令:node

mkdir Webpack-Vue && cd Webpack-Vue && npm init -y
复制代码

而后你就能够在你的当前路径下看到一个叫 Webpack-Vue 的文件夹,里面有一个包含默认信息的 package.json 文件,打开并修改这个文件的一些内容。react

而后咱们在项目文件夹中建立如下几个文件夹:webpack

  • dist
  • src、src/components
  • build

Linux 下能够输入一下命令进行快速建立:git

mkdir src src/components dist build -p
复制代码

其中,dist 用于存放 Webpack 打包后的项目文件、src 用于存放你的源代码文件、build 用于存放 Webpack 打包相关的配置文件。github

在 src 下,建立入口文件 index.jsweb

Linux 下建立的命令:vue-router

touch ./src/index.js
复制代码

在根目录下建立 index.html 文件,内容以下:

<!DOCTYPE html>
<html>
  <head>
    <title>Webpack Vue Demo</title>
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
  </head>
  <body>
    <div id="app"></div>
  </body>
</html>
复制代码

这将用于做为咱们应用的模板,打包的 js 文件会在 Webpack 插件的处理下插入到这个文件中。

其余配置性文件根据你本身的喜爱来添加了,好比 .gitignore 文件等。

2、安装 Webpack

要使用 Webpack,第一步固然是先安装。使用如下命令进行安装:

npm i webpack webpack-cli -D
复制代码

而后你就能够看到你的项目文件夹中多了一个 node_modules 文件夹,而后 package.json 文件中多了一个 devDependencies 属性。里面包含了安装的依赖名称和依赖版本,如今暂时还只有 webpackwebpack-cli

3、配置最基本的 Webpack

这一节咱们将着手配置一个具备最基本打包功能的项目,从 src/index.js 开始对项目进行打包。

为了项目结构更加科学合理,咱们把全部的 Webpack 配置相关的文件都存放在了 build 目录中。

进入 build 文件夹,而后建立如下几个文件:

  • webpack.base.conf.js
  • webpack.dev.conf.js
  • webpack.prod.conf.js
  • build.js

在 Linux 中,能够敲入以下命令快速建立:

cd build/ && touch webpack.base.conf.js webpack.dev.conf.js webpack.prod.conf.js build.js
复制代码

其中,webpack.base.conf.js 是最基础的打包配置,是开发环境和生产环境都要用到的配置。webpack.dev.conf.js 就是在开发环境要使用的配置。webpack.prod.conf.js 就是在生产环境要使用的配置了。build.js 是经过 Node 接口进行打包的脚本。

接下来咱们在对应的文件中写入最基本的配置信息。

(1) webpack.base.conf.js

先写最基本的配置信息:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
  entry: {
    bundle: path.resolve(__dirname, '../src/index.js')
  },
  output: {
    path: path.resolve(__dirname, '../dist'),
    filename: '[name].[hash].js'
  },
  module: {
    rules: [
      
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, '../index.html')
    })
  ]
};
复制代码

(2) webpack.dev.conf.js

一样写入最基本的配置信息:

const merge = require('webpack-merge');
const path = require('path');
const baseConfig = require('./webpack.base.conf');
module.exports = merge(baseConfig, {
  mode: 'development',
  devtool: 'inline-source-map',
  devServer: {
    contentBase: path.resolve(__dirname, '../dist'),
    open: true
  }
});
复制代码

(3) webpack.prod.conf.js

下面的配置中,CleanWebpackPlugin 是 1.x.x 版本的写法,在升级到 2.x.x 版本之后,构造函数的写法发生了变化,详情请参考:clean-webpack-plugin,感谢掘友 @厚厚厚厚厚 的提醒!

继续写入最基础的配置:

const merge = require('webpack-merge');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const path = require('path');
const baseConfig = require('./webpack.base.conf');
module.exports = merge(baseConfig, {
  mode: 'production',
  devtool: 'source-map',
  module: {
    rules: []
  },
  plugins: [
    new CleanWebpackPlugin(['dist/'], {
      root: path.resolve(__dirname, '../'),
      verbose: true,
      dry: false
    })
  ]
});
复制代码

注意到咱们上面引用了两个新的依赖,须要先进行安装才能使用:

cnpm i webpack-merge clean-webpack-plugin webpack-dev-server html-webpack-plugin -D
复制代码

(4) build.js

这个脚本用于构建生产环境,开发环境基于 webpack-dev-server 搭建,不写脚本。

接下来,写入咱们的打包脚本,经过 Node 调用 Webpack 进行打包。

const webpack = require('webpack');
const config = require('./webpack.prod.conf');

webpack(config, (err, stats) => {
  if (err || stats.hasErrors()) {
    // 在这里处理错误
    console.error(err);
    return;
  }
  // 处理完成
  console.log(stats.toString({
    chunks: false,  // 使构建过程更静默无输出
    colors: true    // 在控制台展现颜色
  }));
});
复制代码

这样作的好处是能够利用 Node 作一些其余的事情,另外当 Webpack 配置文件不在项目文件夹根部时方便调用。

(5) npm scripts

配置 npm scripts 可以使咱们更方便的使用打包命令。

package.json 文件的 scripts 属性中,写入以下两条:

"build": "node build/build.js",
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js"
复制代码

基本的配置写完了,咱们测试一下打包效果,在 src/index.js 中写入以下代码:

console.log('index.js!');
复制代码

而后在命令行中输入:

npm run dev
复制代码

在自动打开的网页中,我打开控制台,咱们能够看到输出了一句“index.js”,符合预期。

而后输入构建命令进行构建:

npm run build
复制代码

截图以下:

img

这就表示打包成功了,可是咱们还只完成了最基本的打包功能,Vue 还不能使用,接下来咱们将这个项目变得更增强大。

4、引入一些基础的 Loader

为了方便开发,咱们须要引入一些 Loader,以简化咱们的写法以及使咱们的代码兼容更多的环境。

这一部分能够根据 Webpack 的文档来写,由于都是一些基本的东西,配置起来也不难。

(1)babel-loader

为了使咱们的 JavaScript 代码兼容更多环境,咱们须要使用 babel-loader。

配置方法:

首先安装 babel-loaderbabel-preset-envbabel-core。须要注意的是,若是你的 babel-loader 是 7.x 版本的话,你的 babel-core 必须是 6.x 版本;若是你的 babel-loader 是 8.x 版本的话,你的 babel-core 必须是 7.x 版本。若是不这样的话,Webpack 会报错。

安装命令以下:

npm i babel-loader@7 babel-core babel-preset-env -D
复制代码

而后在 webpack.base.conf.jsmodule.rules 中新增以下对象:

{
  test: /\.js$/,
  use: 'babel-loader',
  exclude: /node_modules/
}
复制代码

咱们还须要添加一个配置文件(.babelrc)在根目录下:

{
  "presets": [
    ["env", {
      "modules": false,
      "targets": {
        "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
      }
    }]
  ]
}
复制代码

这就是 babel-preset-env 的做用,帮助咱们配置 babel。咱们只须要告诉它咱们要兼容的状况(目标运行环境),它就会自动把代码转换为兼容对应环境的代码。

以上代码表示咱们要求代码兼容最新两个版本的浏览器,不用兼容 IE 8,另外市场份额超过 1% 的浏览器也必须支持。

只须要告诉 babel-preset-env 你想要兼容的环境,它就会自动转换,是否是很爽?不再用配置那么多了。

接下来咱们试一试,把 src/index.js 中的代码改写为:

const x = 'index.js';

const y = (x) => {
  console.log(x);
}

y(x);
复制代码

而后使用 npm run build 进行打包,打包以后的代码中:

var x = 'index.js';

var y = function y(x) {
  console.log(x);
};

y(x);
复制代码

说明咱们的代码已经被成功地转换了。

为了作一个对比,未配置 babel 时,转换结果以下:

const x = 'index.js';

const y = (x) => {
  console.log(x);
}

y(x);
复制代码

(2)file-loader

这个用于将字体文件、图片文件进行模块化。

首先安装 file-loader

npm i file-loader -D
复制代码

而后在 webpack.base.conf.js 中添加以下配置到 module.rules

{
  test: /\.(png|svg|jpg|gif)$/,
  use: [
    'file-loader'
  ]
},
{
  test: /\.(woff|woff2|eot|ttf|otf)$/,
  use: [
    'file-loader'
  ]
}
复制代码

固然能够简化配置信息,把两个 test 正则合并到一处。

接下来咱们配置 vue-loader

(3) vue-loader

为了使用 Vue 单文件组件,咱们须要对 .vue 文件进行处理,使用 vue-loader

首先安装 vue-loadercss-loadervue-style-loadervue-template-compiler,后者也是必不可少的,少了会报错。

命令:

npm i vue-loader css-loader vue-style-loader vue-template-compiler -D
复制代码

而后咱们配置 webpack.base.conf.js,写入如下代码到该文件的 module.rules 属性当中:

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

只有这一处配置是不行的,根据 vue-loader 官网的说明,咱们还须要配置一个插件,而后还须要配置 resolve.alias 别名,否则 Webpack 无法找到 Vue 模块。

配置插件,首先在文件头部引入:

const VueLoaderPlugin = require('vue-loader/lib/plugin');
复制代码

而后在 plugins 数组中添加这个插件对象:

new VueLoaderPlugin(),
复制代码

随后咱们还要配置别名,将 resolve.alias 配置为以下对象:

{
  'vue$': 'vue/dist/vue.esm.js',
  '@': path.resolve(__dirname, '../src'),
}
复制代码

这可使得 Webpack 很方便的找到 Vue,咱们在 JavaScript 文件中引入依赖的时候,也能够方便地使用 @ 来代替 src,省去了写文件路径的麻烦。

咱们顺便添加一个 resolve.extensions 属性,方便咱们引入依赖或者文件的时候能够省略后缀:

extensions: ['*', '.js', '.json', '.vue'],
复制代码

extensions 属性是一个数组。这样配置以后,咱们在 JavaScript 文件中 import JavaScript 文件、json 文件和 Vue 单文件组件均可以省略后缀。

以上几步都很重要,最好不要省略。

接下来咱们验证一下 Vue 单文件组件是否可用。

安装 Vue:

npm i vue --save
复制代码

而后修改 index.js 文件内容以下:

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

new Vue({
  el: '#app',
  template: '<App/>',
  components: { App }
});
复制代码

而后在同级目录下建立一个 App.vue 文件,内容以下:

<template>
  <h1>Hello World!</h1>
</template>

<script>
  export default {
    name: 'App'
  }
</script>

<style>
  html, body {
    padding: 0;
    margin: 0;
    box-sizing: border-box;
    font-size: 16px;
  }
</style>
复制代码

运行命令 npm run dev 就能够看到一个大大的一级标题 —— Hello World 啦!

到这里,咱们的项目已经可使用 Vue 单文件组件进行开发了,可是尚未完,咱们还有一些任务要作。

5、优化 CSS 代码

这里咱们使用 postcss 的 autoprefixer 插件为咱们的 css 代码自动添加前缀以适应不一样的浏览器。

首先安装依赖:

npm i postcss-loader autoprefixer -D
复制代码

而后修改 module.rules 中的 css 配置项,修改以后以下:

{
  test: /\.css$/,
  use: ['vue-style-loader', 'css-loader', 'postcss-loader']
}
复制代码

而后在咱们项目的根目录下新增配置文件 postcss.config.js,内容以下:

module.exports = {
  plugins: [
    require('autoprefixer')
  ]
}
复制代码

表明咱们将要使用 autoprefixer 插件。

以后咱们就能够愉快地写代码了,能够本身验证一下是否自动添加了前缀,这里再也不赘述。

6、开启热更新

Webpack 4 开启热更新相对容易,具体步骤以下:

修改 webpack.dev.conf.js,在 devServer 属性中设置 hot 的值为 true,这就表明开启了热更新。可是只这样作还不够,须要咱们添加一个插件,继续修改 webpack.dev.conf.js

设置其 plugins 属性以下:

const webpack = require('webpack');
// 在文件头部引入 webpack 依赖
[
  new webpack.HotModuleReplacementPlugin()
]
复制代码

这就开启了 css 热更新(由于 vue-style-loader 封装了 style-loader,热更新开箱即用),可是 JavaScript 热更新还不能用,每次修改代码咱们都会刷新浏览器,因此咱们须要继续配置。

为了使得 JavaScript 模块也能进行 HMR,咱们须要在咱们的 入口文件(index.js) 的底部添加以下代码:

if (module.hot) {
  module.hot.accept();
}
复制代码

接下来就能够进行 HMR 了。

7、第三方库单独打包

每次咱们对项目进行打包时,咱们都会把引用的第三方依赖给打包一遍,好比 Vue、Vue-Router、React 等等。可是这些库的代码基本都是不会变更的,咱们不必每次打包都构建一次,因此咱们最好将这些第三方库提取出来单独打包,这样有利于减小打包时间。

官方插件是 DllPlugin,可是这个插件配置比较繁琐。网上有人推荐一个比较好用的插件 —— autodll-webpack-plugin,确实很好用。

下面是它的配置方法:

首先安装:

npm i autodll-webpack-plugin -D
复制代码

而后在 webpack.base.conf.js 中引入:

const AutoDllPlugin = require('autodll-webpack-plugin');
复制代码

而后在 plugins 属性中添加这个插件:

new AutoDllPlugin({
  inject: true, // will inject the DLL bundle to index.html
  debug: true,
  filename: '[name]_[hash].js',
  path: './dll',
  entry: {
    vendor: ['vue', 'vue-router', 'vuex']
  }
})
复制代码

inject 为 true,插件会自动把打包出来的第三方库文件插入到 HTML。filename 是打包后文件的名称。path 是打包后的路径。entry 是入口,vendor 是你指定的名称,数组内容就是要打包的第三方库的名称,不要写全路径,Webpack 会自动去 node_modules 中找到的。

每次打包,这个插件都会检查注册在 entry 中的第三方库是否发生了变化,若是没有变化,插件就会使用缓存中的打包文件,减小了打包的时间,这时 Hash 也不会变化。

8、提取共同代码:

使用 splitChucksPlugin 插件,这是 Webpack 自带的,不用安装第三方依赖。

使用方法:

webpack.base.conf.js 的 plugins 属性中添加以下插件对象;

new webpack.optimize.SplitChunksPlugin()
复制代码

这表明你将使用默认的提取配置来提取你的公共代码,若是你不想使用默认配置,请给插件构造函数传入配置对象.

具体怎么配置,请参考冷星大神的博客 —— webpack4——SplitChunksPlugin使用指南,里面关于配置项的做用介绍得很清楚很详细。

9、使用 stylus 预处理器

我我的比较喜欢 stylus,由于写起来比较无拘无束,相似 Python,没那么多条条框框,并且用起来也不是很复杂。

引入方法:

首先下载 stylus 和 stylus-loader 依赖:

npm i stylus stylus-loader -D
复制代码

而后在配置项 module.rules 中添加一个处理 stylus 文件的配置对象。

配置信息以下:

{
  test: /\.styl(us)$/,
  use: ['vue-style-loader', 'css-loader', 'stylus-loader', 'postcss-loader']
}
复制代码

接下来只要你在 Vue 单文件组件的 style 标签加上 lang='stylus',你就可使用 stylus 来写 CSS 了。

10、抽取 CSS 到单文件

这个功能的配置方法在 Vue Loader 官网交代得很清楚了。

使用的是 mini-css-extract-plugin 插件,首先安装:

npm i mini-css-extract-plugin -D
复制代码

而后在配置文件头部引入:

const MiniCssExtractPlugin = require('mini-css-extract-plugin')
复制代码

而后当你要抽取 CSS 的时候(好比生产环境打包),你就把原来配置文件中的全部 vue-style-loader 替换为 MiniCssExtractPlugin.loader,其余的什么 css-loaderstylus-loader 等等都不要动。

最后,修改 plugins 选项,插入以下插件:

new MiniCssExtractPlugin({
  filename: "[name].css",
  chunkFilename: "[id].css"
})
复制代码

打包以后,你会发现全部的 CSS 代码都被抽取到了一个单独的 CSS 文件当中。

收获

  • 配置要谨慎,一个错误就可能致使莫名其妙的报错。
  • 学习 Webpack 要多实践,光理论学起来比较抽象。
  • 多查 Webpack 文档,其实不少问题里面都交代清楚了,不要急于到网上找答案。
  • 现成的脚手架是最好的范例,好比 Vue-Cli,create-react-app。多看看它们是怎么配置的,能够学到一些东西。

示例代码放在个人 GitHub 仓库,须要的同窗能够自取。

若有错误,敬请指出!

相关文章
相关标签/搜索