webpack开发Vue配置
在webpack的世界里,一张图片、一个css甚至一个字体,都成为模块(Module),彼此存在依赖关系,webpack就是来处理模块间的依赖关系的,并把它们进行打包。webpack的主要适用场景是单页面富应用(SPA)。SPA通常是由一个html文件和一堆按需加载组成,它的html结构可能会非常简单,比如:<!DOCTYPE html><html><head>
在webpack的世界里,一张图片、一个css甚至一个字体,都成为模块(Module),彼此存在依赖关系,webpack就是来处理模块间的依赖关系的,并把它们进行打包。
webpack的主要适用场景是单页面富应用(SPA)。SPA通常是由一个html文件和一堆按需加载组成,它的html结构可能会非常简单,比如:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<title>title</title>
<link rel="stylesheet" href="/vonic/vonic.min.css">
</head>
<body>
<von-app></von-app>
<script type="text/javascript" src="dist/main.js"></script>
</body>
</html>
只有一个div节点,所有的代码都集成在了神奇的main.js文件中。
安装webpack与webpack-dev-server
首先,创建一个目录demo,使用NPM初始化配置
npm init
执行后,会有一系统选项,按回车键快速确认,完成后在demo目录生成一个package.json文件。
在本地局部安装webpack:
npm install webpack --save-dev
--save-dev是开发依赖来安装webpack。
安装成功后,在package.json多一项配置:
接着安装webpack-dev-server,它可以在开发环境中提供很多服务,比如启动一个服务器、热更新、接口代理等,配置起来也很简单。在本地局部安装:
npm install webpack-dev-server --save-dev
一个webpack.config.js文件
接下来了解webpack的一些核心概念。
webpack就是一个.js配置文件,架构好或差都体现在这个配置里,随着需求不断出现,工程配置也是逐渐完善的。
首先在目录demo下创建一个js文件:webpack.config.js
var config = {
};
module.exports = config;
然后在package.js里增加一个快速启动webpack-dev-server服务的脚本:
"dev": "webpack-dev-server --open --config webpack.config.js"
接下来运行npm ren dev,会显示下面是否要安装webpack-cli,yes按回车键
当运行npm run dev命令时,就会执行webpack-dev-server --open --config webpack.config.js命令。其中--config是指向webpack-dev-server读取的配置文件路径,这里直接读取我们在上一步创建的webpack.config.js文件。 --open会在执行命令时自动在浏览器打开页面,默认地址是localhost:8080。
如果需要让其他同事访问我的本地,配置--host ip地址:
"dev": "webpack-dev-server --host 100.100.100.1 --port 8888 --open --config webpack.config.js"
webpack配置中最重要也是必选的两项是入口(Entry)和出口(Output)。入口的作用是告诉webpack从哪里开始寻找依赖,并且编译,出口则用来配置编译后的文件存储位置和文件名。
在demo目录下新建一个文件名叫src,src文件里面再新建一个main.js作为入口的文件,加一行代码:
document.getElementById('app').innerHTML = "hello main"
然后在webpack.config.js中进行入口和输出的配置:
var path = require('path');
var config = {
entry: {
main: './src/main.js' // main就是我们配置的单入口,webpack会从main.js文件开始工作
},
output: {
path: path.join(__dirname, './dist'), // 用来存放打包后文件的输出目录
publicPath: '/dist/', // 指定资源文件引用的目录
filename: 'main.js' // 用于指定输出文件的名称
}
};
module.exports = config;
因此,这里配置的output为打包后的文件会存储为demo/dist/main.js文件,只要在html中引入它就可以了。
在demo目录下,新建一个index.html作为我们SPA的入口:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>app</title>
</head>
<body>
<div id="app"></div>
<script type="text/javascript" src="/dist/main.js"></script>
</body>
</html>
在终端执行下面的命令,就自动在浏览器中打开页面了:
npm run dev
出现页面Cannot GET/
以前我做过没问题的,应该是版本问题,排查了是项目不存在,于是查看我用vue2和vue3做过项目,增加static对应项目文件路径,并打开整个项目文件,如下:
var path = require('path');
var config = {
mode: 'development',
entry: {
main: './main.js'
},
output: {
path: path.join(__dirname,'./dist'),
publicPath: '/dist/',
filename: 'main.js',
},
devServer: {
static: './public',
}
};
module.exports = config;
再命令npm run dev,成功了
在demo/src/main.js文件,修改页面的内容:
document.getElementById('app').innerHTML = "hello webpack"
然后保存,没有刷新浏览器,页面内容自动更新了“hello webpack”,这就是webpack-dev-server的热更新功能,它通过建立一个WebSocket连接来实时响应代码的修改。
逐步完善配置文件
在webpack的世界里,每个文件都是一个模块,比如.css、.js、.html、.jpg、.less等。对于不同的模块,需要用不同的加载器(Loaders)来处理,而加载器就是webpack最重要的功能。
通过npm来安装:
npm install css-loader --save-dev
npm install style-loader --save-dev
安装完成后,在webpack.config.js文件里配置Loader,增加对.css文件的处理:
在module对象的rules属性中可以指定一系列的loaders,每一个loader都必须包含test和use两个选项。就是当webpack编译过程中遇到require()或import语句导入一个后缀名为.css的文件时,先将它通过css-loader转换,再通过style-loader转换,然后继续打包。use选项的值可以是数组或字符串,如果是数组,它的编译顺序就是从后往前。
在demo/src目录下新建一个style.css文件,并在main.js中导入:
/* style.css */
#app{
font-size: 22px;
color: red;
}
// main.js
import './style.css'
document.getElementById('app').innerHTML = "hello webpack"
重新执行npm run dev命令,可以看到页面中的文字已经变成红色,并且字号也大了。
看上面,CSS是通过JavaScript动态创建<style>标签来写入的,就是样式代码都已经编译在了main.js文件里,但在实际业务中,因为项目大了样式会很多,都放在JS里太占体积。所以要用到webpack插件extract-text-webpack-plugins。
这个插件功能很强大而且可以定制。这里我们使用这个插件来把散落在各地的css提取出来,并生成一个main.css的文件,最终在index.html里通过<link>的形式加载它。
通过NPM安装extract-text-webpack-plugins插件:
npm install extract-text-webpack-plugin --save-dev
发现提示extract-text-webpack-plugin需要webpack3到4版本,但是我的webpack版本是5.x
npm run dev果然报错
上网搜了搜,由于webpack5以上的版本,只能用mini-css-extract-plugin代替
通过npm来安装:
npm install mini-css-extract-plugin --save-dev
然后在webpack.config.js文件中导入插件,并改写loader的配置:
var path = require('path');
var MiniCssExtractPlugin = require('mini-css-extract-plugin');
var config = {
mode: 'development',
entry: {
main: './src/main.js'
},
output: {
path: path.join(__dirname,'./dist'),
publicPath: '/dist/',
filename: 'main.js',
},
devServer: {
static: './public',
},
module:{
rules: [
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader
},
'css-loader'
]
}
]
},
plugins: [
// 重命名提取后的css文件
new MiniCssExtractPlugin({
filename: 'main.css',
})
]
};
module.exports = config;
在public/index.html文件中,增加一行<link>标签:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>app</title>
<link rel="stylesheet" href="./dist/main.css">
</head>
<body>
<div id="app"></div>
<script type="text/javascript" src="./dist/main.js"></script>
</body>
</html>
重新npm run dev,就可以看到<style>没有了,通过<link>引入的main.css文件已经生效。
单文件组件与vue-loader
vue.js是一个渐进式的JavaScript框架,在使用webpack构建Vue项目时,可以使用一种新的构建模式:.vue单文件组件。在webpack中使用vue-loader就可以对.vue格式的文件进行处理。
使用.vue文件需要先安装vue-loader、vue-style-loader等加载器并做配置。要使用ES6语法,还需要安装babel和babel-loader等加载器。通过NPM安装以下依赖:
npm install --save vue
npm install --save-dev vue-loader
npm install --save-dev vue-style-loader
npm install --save-dev vue-template-compiler
npm install --save-dev vue-hot-reload-api
npm install --save-dev babel
npm install --save-dev babel-loader 8版本,下面与这个版本的对应关系
npm install --save-dev @babel/core
npm install --save-dev @babel/preset-react
npm install --save-dev @babel/preset-env
npm install --save-dev babel-preset-mobx
npm install --save-dev @babel/plugin-transform-runtime
npm install --save @babel/runtime
安装完成后,修改配置文件webpack.config.js来支持对.vue文件:
var path = require('path');
var MiniCssExtractPlugin = require('mini-css-extract-plugin');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
var config = {
mode: 'development',
entry: {
main: './src/main.js'
},
output: {
path: path.join(__dirname,'./dist'),
publicPath: '/dist/',
filename: 'main.js',
},
devServer: {
static: './public',
},
module:{
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
css: [
{
loader: MiniCssExtractPlugin.loader
},
'vue-style-loader',
'css-loader'
]
}
}
},
{
test: /\.js$/ ,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader
},
'css-loader'
]
}
]
},
plugins: [
// 重命名提取后的css文件
new MiniCssExtractPlugin({
filename: 'main.css',
}),
new VueLoaderPlugin()
]
};
module.exports = config;
vue-loader在编译.vue文件时,会对<template>、<script>、<style>分别处理,所以在vue-loader选项里多了一项options来进一步对不同语言进行配置。比如在对css进行处理,会先通过css-loader解析,然后把处理结果再交给vue-style-loader处理。当你的技术栈多样化时,比如<style lang="less">,配置loaders就可以了。
再npm run dev,先看看有没有提示刚才安装依赖版本问题,如果有问题,请自行百度,如果没有问题,继续下一步。
支持ES6的解析,在demo目录下新建一个名为.babelrc的文件,并写入babel的配置,webpack会回复此配置文件来使用babel编译ES6代码:
{
"presets": ["@babel/preset-env", "@babel/preset-react", "mobx"],
"plugins": [
"@babel/plugin-proposal-object-rest-spread",
"@babel/plugin-transform-runtime"
]
}
在demo/src目录下新建一个app.vue的文件并写入以下内容:
<template>
<div id="app">
<div>Hello {{ name }}</div>
</div>
</template>
<script>
export default {
data() {
return {
name: 'Vue.js'
}
},
}
</script>
<style scoped>
#app{
font-size: 24px;
color: red;
}
</style>
<style scoped>中 scoped属性,这部分样式只会对当前组件app.vue有效,如果不加这个属性的话会统一提取并打包在main.css里。
main.js文件中,把内容替换为下面的代码:
import Vue from 'vue';
import App from './app.vue';
new Vue({
el: '#app',
render: h => h(App)
})
用于生产环境
我们先对webpack进一步配置,来支持更多常用的功能。
安装url-loader和file-loader来支持图片、字体等文件:
npm install --save-dev url-loader
npm install --save-dev file-loader
webpack.config.js增加下面代码:
{
test: /\.(png|jpe?g|gif|svg)\??.*$/,
loader: 'url-loader',
options: {
limit: 1024,
esModule: false
}
}
当遇到这些格式文件时,url-loader会把它们一起编译到dist目录下,limit:1024是如果这个文件小于1kb,就以base64的形式加载,不会生成一个文件。
下面webpack打包的产物。
单页面富应用(SPA)技术,最终只有一个html的文件,其余都是静态资源。实际部署到生产环境时,一般会将html挂在后端程序下,由后端路由渲染这个页面,将所有的静态资源(css、js、img、iconfon等)单独部署到CDN,这样就实现了前后端完全分离。
在package.json中,再加入一个build的快捷脚本用来打包:
"scripts": {
"build": "webpack --config webpack.prod.config.js --mode development"
},
用--mode production打包出来就被压缩,空行和注释消失;
用--mode development打包出来就是未压缩的;
打包需要两个依赖,通过NPM安装:
npm install --save-dev webpack-merge
npm install --save-dev html-webpack-plugin
为了方便开发和生产环境的切换,在demo目录下新建一个用于生产环境的配置文件webpack.prod.config.js:
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var MiniCssExtractPlugin = require('mini-css-extract-plugin');
var { merge } = require('webpack-merge'); //{ merge }通过es6提供的解构赋值,即按需加载
var webpackBaseConfig = require('./webpack.config.js');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
webpackBaseConfig.plugins = [];
module.exports = merge(webpackBaseConfig,{
output: {
publicPath: '/dist/',
// 将入口文件重命名为带有20位hash值得唯一文件
filename: '[name].[hash].js',
},
plugins:[
new MiniCssExtractPlugin({
// 提取css,并重命名为带有20位hash值得唯一文件
filename: '[name].[hash].css',
}),
// 定义当前 node 环境为生产环境
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify("development"),
}
}),
// 提取模板,并保存入口 html 文件
new HtmlWebpackPlugin({
filename: './index.html',
template: './index.ejs',
inject: false
}),
// vue-loader 15.x 以上版本需要配置
new VueLoaderPlugin()
]
})
上面安装的webpack-merge模块就是用于合并两个webpack的配置文件,所以prod的配置是在webpack.config.js基础上扩展的。静态资源在大部分场景下都有缓存(304),更新上线后一般都希望用户能及时看到最新内容,所以给打包后的css和js文件的名称都加了20位的hash值,这样文件名就唯一了,只要不对html文件设置缓存,上线后立即就可以加载最新的静态资源。
html-webpack-plugin是用来生成html文件的,它通过template选项来读取指定的模板.ejs,然后输出到filename指定的目录。模板index.ejs动态设置静态资源的路径和文件名,代码如下:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Webpack App</title>
<link rel="stylesheet" href="<%= htmlWebpackPlugin.files.css[0] %>">
</head>
<body>
<div id="app"></div>
<script type="text/javascript" src="<%= htmlWebpackPlugin.files.js[0] %>"></script>
</body>
</html>
在终端运行npm run build,等待一会就完成打包,成功后在demo下回生成一个dist的目录。
每次打包前没有删除上一个dist文件,只会在旧dist文件里面叠加一些文件,我们想要打包前自动删除上一个dist文件
通过NPM安装clean-webpack-plugin:
npm install --save-dev clean-webpack-plugin
在webpack.config.js引入如下代码:
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
在plugins中配置:
new CleanWebpackPlugin()
在终端运行npm run build,就可以自动删除上一个dist文件,然后重新进行打包,生成干净的dist目录。
在vue3没公布之前,我学过webpack配置到打包,现在再次使用最新版本的webpack5,babel-loader 8版本,兼容这些版本做出配置,多一些新东西,多学到一些新知识。webpack还有很多高级的配置和丰富的插件及加载器,等着我学。活到老,学到老。
更多推荐
所有评论(0)