webpack4.0 + vue2.0 (一)

本文深入讲解Webpack配置与优化,涵盖VSCode插件推荐、ESLint集成、AutoSave设置、Webpack基本配置、html-webpack-plugin和clean-webpack-plugin应用、WebpackManifestPlugin详解、Babel与Vue集成、开发工具与模式介绍、css预处理器及性能优化策略。

这篇主要是对我学习webpack文档是的记录笔记,大家也可自行看webpack官方文档

vscode编译器

建议插件安装: vetur、autosave、eslint

eslint

vscode终端运行以下

npm install eslint -g //第一步
eslint --init 
//第一部成功之后运行,这部之后会出现一些eslint配置选择,根据自己实际需求选择回车,eg项目为vue会提示你是否要安装eslint-plugin-vue,y回车
//完成之后会自动生成.eslintrc.js文件,rules规则查看eslint官网
//https://eslint.org/docs/rules/
autoSave

autoSave需要在setting里面设置onFocusChange

webpack配置
  • 基本安装package.json
mkdir webpack-demo
cd webpack-demo
npm init -y
npm install webpack webpack-cli --save-dev

为了确保我们的代码不意外发布,可以调整package.json文件,添加属性"private": true,移除"main": "index.js"

package.json

 {
    "name": "webpack-demo",
    "version": "1.0.0",
    "description": "",
    "private": true,  //添加此属性
    "main": "index.js",  //移除此属性
    "scripts": {
      "test": "echo \"Error: no test specified\" && exit 1",
      "build": "webpack"  //其实就是webpack --config webpack.fonfig.js
    
    },
    "keywords": [],
    "author": "",
    "license": "ISC",
    "devDependencies": {
      "webpack": "^4.20.2",
      "webpack-cli": "^3.1.2"
    },
    "dependencies": {}
  }

注意: 另外不同平台设置环境变量的方式是不一样的,eg:(mac)set NODE_ENV=production;(window)NODE_ENV=production;所以我们这里用cross-env
安装:npm i cross-env
package.json:
"build": "cross-env NODE_ENV=production webpack", "dev": "cross-env NODE_ENV=devlopment webpack-dev-server --open",

文件基本结构
在这里插入图片描述
index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    
</head>
<body>
    
</body>
</html>
<script src="main.js"></script>

index.js

function component() {
    const element = document.createElement('div');

    element.innerHTML = 'Hello webpack and vue'

    return element;
  }

  document.body.appendChild(component());
npx webpack //运行测试  也可通过在package.json scripts添加build命令 
webpack.config.js
const path = require('path');  //绝对路径   node的基本设置  道友可以输出看path是什么

module.exports = {
    entry: './src/index.js',  //path.join(__dirname, 'src/index.js') 绝对路径拼接
    output: {
        filename: 'main.js',
        path: path.resolve(__dirname, 'dist') ,//path.join(__dirname, 'dist') 绝对路径拼接 打包后文件的输出路径
        publicPath: '/' //打包后生成的静态资源文件路径前缀
    }
}
html-webpack-plugin

到目前为止,我们已经手动将所有资产包含在index.html文件中,但是随着应用程序升级,如果开始在文件名中使用散列并输出多个包,就很难继续手动管理index.html文件。如下:
新建print.js
在这里插入图片描述
print.js

export default function printMe() {
  console.log('I get called from print.js!');
}

index.html调整

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>output Management</title>
    <script src="./print.bundle.js"></script>
</head>
<body>
    
</body>
</html>
<script src="./app.bundle.js"></script>

webpack.config.js调整

entry: {
        app: './src/index.js',
        print: './src/print.js'
    },
    output: {
        filename: '[name].bundle.js',
        path: path.resolve(__dirname, 'dist')
    },

index.js

import printMe from './print.js'

function component() {
    const element = document.createElement('div');
    const btn = document.createElement('button');

    element.innerHTML = 'Hello webpack and vue'
    btn.innerHTML = 'Click me and check the console!';
    btn.onclick = printMe;

    element.appendChild(btn);
    return element;
  }

  document.body.appendChild(component());
npm run build   //运行看下效果

如上如果我们有好多js文件就很麻烦一直手动添加所以开始HtmlWebpackPlugin的表演
安装

npm install --save-dev html-webpack-plugin

配置

const HtmlWebpackPlugin = require('html-webpack-plugin')
config.plugin.push(new HtmlWebpackPlugin({
            title: 'Output Management',
        }))

npm run build运行如下:
在这里插入图片描述
默认生成一个新的index.html即使之前dist/index.html已经存在,新的index.html文件将会取代旧的文件并且新的文件包含你所有的js打包文件,可以打开你的index.html文件看看

html-webpack-plugin

如果按照我的步骤构建,你可能会发现我们的dist文件变得相当混乱,Webpack将生成文件并将它们放在/dist文件夹中,但它不会跟踪项目实际使用的文件。
一般来说,在每次生成之前清理/dist文件夹是一个很好的做法,这样只会生成使用过的文件。好该我们的html-webpack-plugin表演了

安装

npm install --save-dev clean-webpack-plugin

配置

const { CleanWebpackPlugin } = require('clean-webpack-plugin');
config.plugin.push(new CleanWebpackPlugin())
npm run build      //看看运行之后是不是一下舒爽了哈哈
WebpackManifestPlugin

如果你想知道webpack及其插件是如何“知道”正在生成哪些文件的。答案就在webpack用来跟踪所有模块如何映射到输出包的清单中WebpackManifestPlugin

Using source maps

当webpack打包源代码时,很难跟踪到他们的精确位置。例如,如果将三个源文件(a.js、b.js和c.js)打包到包(bundle.js)中,并且其中一个源文件包含错误,那么堆栈跟踪将只指向bundle.js。所以这可能不是太友好。
webpack.config.js

config.devtool = 'inline-source-map',

你可以随便改一下你的js文件,运行之后你的控制台会报错(跟踪到源文件)

webpack开发工具
  1. Using Watch Mode
    package.json
 "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "watch": "webpack --watch",
    "build": "webpack"
  },
监听你的webpack项目文件更新,当你运行npm  run watch时,你会发现你的命令行并没有退出,因为webpack此时正在监视你的文件,当你有文件更新的话会自动recompile,这是只需要刷新你的页面就可以看到你要的效果。

ps:watch启动之后正常,dist文件夹下存在index.html但是我改动文件保存命令行自动编译之后index.html文件消失了我是按照webpack文档搞得但是我没得看到正常效果哈哈哈

我们继续哈如果自动编译加上自动刷新岂不更好看👇

  1. Using webpack-dev-server
    安装
npm install --save-dev webpack-dev-server

webpack.config.js

config.devServer = { 
contentBase: './dist', //如果不设置会默认是output.publicPath,如果他也没有则取默认值 “/” 
publicPath: './' //devServer里面的publicPath表示的是打包生成的静态文件所在的基础路径(怎么去保存资源)。并且它的优先级是最高的。而output.publicPath代表的是index.html文件里面引用资源的前缀(要怎么去访问资源)
},

这里开启一个服务,localhost:8080指向dist文件

package.json

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "watch": "webpack --watch",
    "build": "webpack",
    "dev": "webpack-dev-server --open" //webpack-dev-server --config webpack.config.js --open (open属性可在devServer里面设置)
  },

注意webpack-dev-server webpack开发服务器在编译后不会写入任何输出文件(即dist文件夹下没有任何输出文件)。相反,它将捆绑文件保存在内存中,并将它们当作真正的文件安装在服务器的根路径上。如果您的页面希望在不同的路径上找到捆绑包文件,您可以使用dev服务器配置中的publicPath选项来更改它。

webpack-dev-middleware

webpack开发中间件是一个包装器,它将webpack处理的文件发送到服务器。这在webpack dev服务器内部使用,但是如果需要,它可以作为一个单独的包来允许更多的自定义设置。我们将看一个结合webpack开发中间件和express服务器的示例。

安装

npm install --save-dev express webpack-dev-middleware

webpack.config.js

output: {
        filename: '[name].bundle.js',
        path: path.resolve(__dirname, 'dist'),
        publicPath: '/',  //注意这时候如果运行watch会有打包路径错误
    },

publicPath也将在我们的服务器脚本中使用,以确保在http://localhost:3000上正确地提供文件。稍后我们将指定端口号。下一步是设置我们的自定义express服务器:

新增server.js(webpack.config.js同级)

const express = require('express');
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');

const app = express();
const config = require('./webpack.config.js');
const compiler = webpack(config);

// Tell express to use the webpack-dev-middleware and use the webpack.config.js
// configuration file as a base.
app.use(webpackDevMiddleware(compiler, {
  publicPath: config.output.publicPath,
}));

// Serve the files on port 3000.
app.listen(3000, function () {
  console.log('Example app listening on port 3000!\n');
});

package.json(scripts新增)

"server": "node server.js"

注意这个运行走的时server.js指定的端口

ps: 突然有疑问那webpack-dev-server和webpack-dev-middleware+express有什么区别呢?

  1. webpack-dev-server是基于webpack-dev-middleware+express的轻型封装,是一个独立使用的开发工具,适合于纯前端开发。
  2. webpack-dev-middleware是一个可以和express配合的开发服务器中间件,通过定义webpack.config,webpack就能依此梳理出所有模块的关系脉络,而WEBPACK-DEV-MIDDLEWARE就在此基础上形成一个微型的文档映射系统。
  3. 为什么上面运行dev和server都没有在dist文件夹下生成文件呢?因为他们都用到了WEBPACK-DEV-MIDDLEWARE,而它就是一个运行于内存中的文档系统,输出的文件存在于内存中,所以重建速度非常快,很适合于开发阶段用作静态资源服务器。
  4. 两者区别仅在于WEBPACK-DEV-SERVER是封装好的,除了webpack.config 和命令行参数之外,你很难去做定制型开发。而express + webpack-dev-middleware适合于定制开发后端服务整合

区别参考文章:
webpack大专栏
webpack-dev-server和webpack-dev-middleware的区别
webpack之开发环境概念集

Babel
npm install --save-dev @babel/core @babel/cli @babel/preset-env
npm install --save @babel/polyfill
npm install --save-dev @babel/plugin-transform-runtime
npm install --save @babel/runtime
Vue
npm vue相关

vue的模块化:vue的各个模块依赖通过webpack打包成一个js文件,使得vue可复用组件贯穿前端整个vue项目,同时减少http资源请求。

npm install vue vue-loader vue-template-compiler vue-loader-plugin
npm install --save-dev style-loader css-loader
npm install vue-router

可自行选择ui框架,这里是elementui,另外如果需要element定制主体,因为他是scss编译,所以可以安装sass sass-loader
安装sass前可以先配置淘宝镜像:

npm config set registry https://registry.npm.taobao.org
npm config get registry  //验证是否配置成功

如果未配置镜像可能会出现以下警告
在这里插入图片描述

npm install sass sass-loader@7.0.3 node-sass -save-dev //要注意这里的sass-loader版本依赖
npm install element-ui -S

如果用到vuex、vue-router

npm install vuex --save
npm install vue-router

webpack.config.js

const path = require('path');  //绝对路径   node的基本设置
const webpack = require('webpack')
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const VueLoaderPlugin = require('vue-loader/lib/plugin')
const isDev = process.env.NODE_ENV === 'devlopment'

const config = {
    entry: {
        app: './src/index.js',
        print: './src/print.js'
    },
    output: {
        filename: '[name].bundle.js',
        path: path.resolve(__dirname, 'dist'),
        publicPath: '/',
    },
    devtool: 'inline-source-map',
    resolve: {
        alias: {
            'vue$': 'vue/dist/vue.esm.js' // 用 webpack 1 时需用 'vue/dist/vue.common.js'
        }
    },
    module: {
        rules: [
            {
                test: /\.vue$/,
                use: [
                    'vue-loader'
                ]
            },
            {
                test: /\.styl$/,
                use: [
                    'style-loader',
                    'css-loader',
                    'stylus-loader'
                ]
            },
            {
                test: /\.css$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    // 'style-loader',
                    { loader: 'css-loader', options: { importLoaders: 1 } },
                    {
                        loader: 'postcss-loader',
                        options: {
                            ident: 'postcss',
                            plugins: [
                                require('autoprefixer')(),
                            ]
                        }
                    },
                    'sass-loader',
                ]
            },
            {
                test: /\.(eot|svg|ttf|woff|woff2)(\?\S*)?$/,
                loader: 'file-loader'
            },
            {
                test: /\.(jpg|png|gif|jpeg|svg)$/,
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            limit: 1024,
                            name: '[name]-p.[ext]'
                        }
                    },
                    // 'file-loader'
                ]
            }
        ]
    },
    plugins: [
        new MiniCssExtractPlugin({
            filename: '[name].[contenthash].css',
            chunkFilename: '[id].[contenthash].css',
            ignoreOrder: false,
        }),
        new HtmlWebpackPlugin({
            title: 'webpack',
        }),
        new CleanWebpackPlugin(),
        new VueLoaderPlugin(),
        new webpack.DefinePlugin({
            'process.env': {
                NODE_ENV: isDev ? '"devlopment"' : '"production"'
            }
        })
    ]
}

if (isDev) {
    config.devServer = {
        port: '5000',
        host: '192.168.124.32',
        hot: true,
        contentBase: './dist',
        publicPath: '/',
        inline: true,
        // lazy: true
    }
    config.plugins.push(
        new webpack.HotModuleReplacementPlugin(),
        new webpack.NoEmitOnErrorsPlugin()
    )
}

module.exports = config

//修改之前的htmlwebpackplugin配置,为什么这样需要探究

因为我们之前用webpack-dev-server运行的话输出的文件都是存在于内存中(dist下没有生成文件),但是vue的挂载点找的是html页面的挂载元素,所以我们需要再webpack.config.js同级新建一个index.html,同时修改htmlwebpackplugin配置如上

index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Output Management</title>
</head>
<body>
  <div id="app"></div>
</body>
</html>

index.js

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

new Vue({
  el: '#app',
  data: {
    
  },
  render: h => h(App)
})

app.vue(index.js同级)

<template>
  <div id="app">
    {{message}}
  </div>
</template>
<script>
export default {
  data(){
    return {
      message: 'hello vue'
    }
  }
}
</script>

或者
index.js

import Vue from 'Vue'  //注意这个是大写啊
import router from './router/index.js'
import App from './app.vue'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import '../style/common.css'

console.log(router)
Vue.use(ElementUI)
var root = document.createElement('div')
document.body.appendChild(root)

new Vue({
  router,
  data: {

  },
  render: h => h(App)
}).$mount(root)

/router/index.js

import Vue from 'Vue'
import VueRouter from 'vue-router'
import Login from '../view/login.vue'
import Home from '../view/home.vue'

Vue.use(VueRouter) //register vue-router

const routes = [
  {
    name: 'Login',
    component: Login,
    path: '/'
  },
  {
    name: 'home',
    component: Home,
    path: '/home'
  }
]

const router = new VueRouter({
  routes
})

export default router
  1. webpack用正则表达式去决定一个文件应该找哪种特定的loader,这种情况下,任何以css为结尾的文件都将送达 style-loader and the css-loader
  2. 你可以通过import './style.css'引入样式文件依赖,当模块运行的时候,带有字符串化css的标签将以style标签形式插入到html文件的head标签里
  3. npm run build比的项目看webpack做了什么,检查页面(不要查看页面源代码,因为它不会显示结果,因为
处理图片像背景或者icon

安装

npm install --save-dev file-loader  url-loader

配置

//这里可用export default config然后就可以属性访问等操作
module.rules.push({
                test: /\.(jpg|png|gif|jpeg|svg)$/,
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            limit: 1024,
                            name: '[name]-p.[ext]'
                        }
                    },
                    // 处理font字体
                    {
			          test: /\.(woff|woff2|eot|ttf|otf)$/,
			          use: [
			           'file-loader',
			          ],
			        },
                ]
            })

file-loader和url-loader区别看这里

推荐css预处理器

安装

npm install stylus-loader stylus

配置

{
                test: /\.styl$/,
                use: [
                    'style-loader',	//碱处理后的style标签文件插入html的header标签里
                    'css-loader',		//css-loader处理后缀名为css的文件加载style标签
                    'stylus-loader'   //stylus-loader处理后缀名为styl的文件加载css
                ]
            },

bg.styl

body
  background bule
css性能优化

webpack来管理css(合并),并增加hash(性能优化)

  1. 压缩:minimize css
  1. 这个插件将CSS提取到单独的文件中。它为每个包含CSS的JS文件创建一个CSS文件。它支持按需加载CSS和sourcemap。(webpack4.0新增特性
  2. 和extract-text-webpack-plugin比较:异步加载、无重复编译(性能)、更易用、特定于css
  3. 建议将mini css extract plugin与css加载程序结合使用
    安装
npm install --save-dev mini-css-extract-plugin

配置
基本配置:

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

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      // Options similar to the same options in webpackOptions.output
      // all options are optional
      filename: '[name].css',
      chunkFilename: '[id].css',
      ignoreOrder: false, // Enable to remove warnings about conflicting order
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              // you can specify a publicPath here
              // by default it uses publicPath in webpackOptions.output
              publicPath: '../',
              hmr: process.env.NODE_ENV === 'development',
            },
          },
          'css-loader',
          // 'postcss-loader','sass-loader',
        ],
      },
    ],
  },
};

长期缓存配置

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

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      filename: '[name].[contenthash].css',
      chunkFilename: '[id].[contenthash].css',
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader'],
      },
    ],
  },
};

更多mini-css-extract-plugin配置请看这里

注意:如果你用的是webpack4.0,然后使用extract-text-webpack-plugin来抽离css,会有如下警告,因为该插件是基于webpack3.0.2的,可以通过webpack4.0支持的beta版本sudo npm install --save-dev extract-text-webpack-plugin@next但是慎用具体看这里

在这里插入图片描述
2. postcss

  1. increase code readability → Autoprefixer
  2. Use tomorrow’s CSS ,today! → postcss-cssnext
  3. The end of global CSS → postcss-modules
  4. Avoid errors in your CSS → stylelint
  5. Powerful grid CSS → lost →lost

先占个坑后面再填

postcss作用
安装

npm install -D postcss-loader postcss-import postcss-preset-env cssnano
  1. postcss-preset-env已经包含了autoprefix,不需要再单独安装autoprefixer
  2. IE浏览器测试可能会遇到的问题:
    localhot不能访问:IE -Internet设置-连接-局域网设置-代理服务器后面的 高级 选项 弹出的页面下方有个不使用代理服务器链接的地方 输入 *localhost 然后再试试

配置
postcss.config.js

module.exports = {
    // parser: 'sugarss',
    plugins: {
      'postcss-import': {},
      'postcss-preset-env': {},
      'cssnano': {}
    }
  }

webpack.config.js
在这里插入图片描述

vue项目踩坑
  1. vue1.0 启动时,如果出现以下错误
    在这里插入图片描述
    这个是vue2.0之后加入了vue-template-compiler编译模块
    解决方法:把node_modules 删除之后,输入以下命令(一定这个顺序):
npm install vue-template-compiler -D //第一步
	
npm install //第二部
	
npm run dev //第三步
  1. 如果出现can‘t find module ’xxx’;一般是loader相关配置的问题

    根据npm报错执行相应loader的install即可

  2. 安装sass警告
    在这里插入图片描述
    注意版本依赖问题,解决方法如下:npm install sass sass-loader@7.0.3 node-sass -save-dev

  3. request@2.88.2警告
    配置淘宝镜像npm config set registry https://registry.npm.taobao.org
    检查是否配置成功npm config get registry

  4. elementui启动报错
    在这里插入图片描述
    是因为没有配置ttf、woff等的loader处理方法
    webpack.config.js添加如下:

{
    test: /\.(eot|svg|ttf|woff|woff2)(\?\S*)?$/,
     loader: 'file-loader'
 },
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值