前言
最近在总结深入自身掌握的知识点, 然后试着从零开始构建一个完整的webpack + VUE的项目. 然后通过
项目对整体流程进行了一个归纳总结, 文章会挺长, 分篇上传吧, 内容方面就以当前在做的后台
项目为示例对象, 发表一些个人归纳的东西, 希望对大家会有一定帮助. 当然, 还是那句话, 每个人的理
解观念不同, 也希望不足的地方能够得到指出补充.
正文
使用webpack初始化构建项目
1. 生成package.json文件
npm init
2. 安装webpack
npm install -g webpack 全局安装
npm install --save-dev webpack 在本地项目中安装
3. 初步搭建项目结构
其中, dist为webpack打包后, 资源存放的文件夹
src为项目主体内容, 也就是页面,路由等开发文件夹
package.json 为当前项目总体信息
webpack.config.js 为webpack的内置配置,之后可以在这个文件中进行一些初始化配置
index.html 为项目主体html文件
- 初步了解webpack配置规则
关于webpack的配置规则, 在这里就初步了解下常用的几个属性的含义和用法, 具体内容不需要太关注,
主要是了解属性的作用
const path = require('path');
const webpack = require('webpack');
//使用该插件 会清理每次打包后, 过去遗留在dist中的旧代码
const {CleanWebpackPlugin} = require("clean-webpack-plugin");
// 使用该插件 , 会解析vue文件
const VueLoaderPlugin = require('vue-loader/lib/plugin');
// 使用该插件,会自动创建并更新html文件
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
// 入口,起点或是应用程序的起点入口。从这个起点开始,应用程序启动执行。如果传递一个数组,那么数组的每一项都会执行。
// 每个 HTML 页面都有一个入口起点。单页应用(SPA):一个入口起点,多页应用(MPA):多个入口起点。
// 一般指向项目中,src目录下的main.js文件
entry:{
app:'./src/main.js'
},
// 输出, 指示 webpack 如何去输出、以及在哪里输出你的「bundle、asset 和其他你所打包或使用 webpack 载入的任何内容」
// 指的是通过webpack打包后的生成的文件以什么名称, 放置在什么位置, 这里一般放置在dist目录下,
output:{
// 将所有依赖的模块合并输出到一个叫bundle.js文件内
filename:'bundle.js',
// 分别对应名称输出
filename: '[name].[hash].js'
// 将输出的文件都放在dist目录下
path:path.join(__dirname,'./dist')
},
// 这个属性,用于设定项目中不同类型的模块所对应的处理规则, 即用到的一些, 诸如sass,less, css, vue, 图片, 文件, 都在
这个属性中进行设置处理规则, 当然, 都会有对应处理的loader. loader 用于对模块的源代码进行转换
module: {
rules: [
{
test: /\.vue$/, // 匹配对象的后缀, 如这里匹配.vue文件
use: [{ // 用于转换该文件类型的loader,
loader: 'vue-loader',
options: { // 内部配置
loaders: {
'scss': 'style-loader!css-loader!sass-loader'
}
}
}],
},
{
test: /\.css$/,
use: ['vue-style-loader','css-loader'] // 使用vue-style-loader直接插入到style标签中
},
{
test: /\.(eot|svg|ttf|woff|woff2)(\?\S*)?$/,
loader: 'file-loader'
},
{
test: /\.scss$/,
// 这里注意一点, use为数组时, 即多loader作用时, 执行规则从后到前, 先使用数组末尾的loader执行转换
use: ['style-loader', 'css-loader', 'sass-loader']
}
]
},
// 自定义webpack构建过程, 例如,当多个 bundle 共享一些相同的依赖,使用 CommonsChunkPlugin 有助于提取这些依赖到共享的 bundle 中,来避免重复打包
plugins:[
new HtmlWebpackPlugin({
template:'index.html',
filename:'index.html'
}),
new VueLoaderPlugin(),
new webpack.HashedModuleIdsPlugin(),
new CleanWebpackPlugin()
],
// 配置模块如何被解析, 即设定相对应模块的解析规则
resolve: {
// 自动补全的扩展名
extensions: ['.js', '.vue', '.json'],
// 默认路径代理
// 例如 import Vue from 'vue',会自动到 'vue/dist/vue.common.js'中寻找
// 这样可以使之后在开发项目的时候, 引用文件时不必关注不同层级的问题
alias: {
'@': path.join(__dirname, './', 'src'),
'@api': path.join(__dirname, './', 'src/api'),
'@styles': path.join(__dirname, './', 'src/styles'),
'@config': path.join(__dirname, './', 'config'),
'vue$': 'vue/dist/vue.common.js',
'@components':path.join(__dirname, './', 'src/components')
}
}
}
-
初步启动项目
- 首先将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> <script src="/dist/build.js"></script> </body> </html> - 在src目录下创建主体入口的main.js文件, 创建一个demo.js示例文件 demo.js示例文件中
export default function say() { console.log('hello world'); }main.js文件中
import say from './util'; say();- 基本信息处理完成后, 就需要初步配置webpack文件了, 先简单的配个出口和入口
var path = require('path'); var webpack = require('webpack'); module.exports = { entry: './src/main.js', // 项目的入口文件,webpack会从main.js开始,把所有依赖的js都加载打包 output: { path: path.resolve(__dirname, './dist'), // 项目的打包文件路径 publicPath: '/dist/', // 通过devServer访问路径 filename: 'build.js' // 打包后的文件名 }, devServer: { historyApiFallback: true, overlay: true } };- 启动之前, 我们需要修改一下package.json. 添加两条启动命令 package.json
"scripts": { // webpack-dev-server会自动启动一个静态资源web服务器 --hot参数表示启动热更新 "dev": "webpack-dev-server --open --hot", "build": "webpack --progress --hide-modules" },- 这样执行npm run dev , 就可以初步启动项目了, 然后随意修改util.js, 可以发现浏览器会
自动刷新, 很方便, 如果需要看打包后的bundle.js文件, 可以执行 npm run build,就可以在
dist文件夹下看到生成的bundle.js.
- 首先将index.html内部代码完善
-
引入vue
- 首先安装vue,
npm i vue --save
2.然后修改main.js文件和index.html文件, 以及webpack.config.js文件
main.jsimport Vue from 'vue'; var app = new Vue({ el: '#app', data: { message: 'Hello Vue!' } });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"> {{message}} </div> <script src="/dist/build.js"></script> </body> </html>webpack.config.js
var path = require('path'); var webpack = require('webpack'); module.exports = { entry: './src/main.js', output: { path: path.resolve(__dirname, './dist'), publicPath: '/dist/', filename: 'build.js' }, devServer: { historyApiFallback: true, overlay: true }, resolve: { alias: { // 添加识别路径 'vue$': 'vue/dist/vue.esm.js' } } };到这, 重新运行 npm run dev, 就可以了.
- 首先安装vue,
-
引入scss和css
- 安装相应的loader
npm i node-sass css-loader vue-style-loader sass-loader --save-dev - 修改 webpack.config.js
var path = require('path'); var webpack = require('webpack'); module.exports = { entry: './src/main.js', output: { path: path.resolve(__dirname, './dist'), publicPath: '/dist/', filename: 'build.js' }, devServer: { historyApiFallback: true, overlay: true }, resolve: { alias: { 'vue$': 'vue/dist/vue.esm.js' } }, module: { rules: [ { test: /\.css$/, //匹配后缀名为css的文件 use: [ //分别用css-loader,vue-style-loader去解析 // 解析器的执行顺序是从下往上(先css-loader再vue-style-loader) // 因为我们这里用vue开发,所以使用vue-style-loader,其他情况使用style-loader 'vue-style-loader', 'css-loader' ], }, // 下列同理 { test: /\.scss$/, use: [ 'vue-style-loader', 'css-loader', 'sass-loader' ], }, { test: /\.sass$/, use: [ 'vue-style-loader', 'css-loader', 'sass-loader?indentedSyntax' ], } ] } };- 在src目录下新建style文件夹, 新建common.scss,写个样式, 然后在main.js中引入 common.js
body { background: #fed; }main.js
import './style/common.scss';
当然, 这里在引入文件的时候,我们可以像上述讲过的, 在webpack.config.js中的resolve里,配置一下
文件引入的规则resolve: { alias: { // 添加识别路径 'vue$': 'vue/dist/vue.esm.js', '@style': path.join(__dirname, './', 'src/style'), } }配置完成后, 就可以直接引入
@style/common.scss这样也是能指向正确的文件的, 这个在项目中会比较实用 - 安装相应的loader
8.使用babel转码, 可以将ES6转码成ES5语法, 这样就可以在项目中使用最新特性了
-
安装
npm i babel-core babel-loader babel-preset-env babel-preset-stage-3 --save-dev
2.在项目根目录新建一个.babelrc文件, 写入内容, 然后在webpack.config.js中添加一个loader
.babelrc{ "presets": [ ["env", { "modules": false }], "stage-3" ] }webpack.config.js
.... { test: /\.js$/, loader: 'babel-loader', // exclude表示忽略node_modules文件夹下的文件,不用转码 exclude: /node_modules/ }- 安装babel-polyfill, 然后修改webpack.config.js的入口
npm i babel-polyfill --save-dev
修改 webpack.config.jsentry: ['babel-polyfill', './src/main.js'],这样就可以测试async, await等es6的语法了.
-
引入图片, 文件, 等等就不细说了, 方式都一样.
npm i file-loader --save-dev
然后添加一个loader
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'file-loader',
options: {
name: '[name].[ext]?[hash]'
}
}
- devServer, 在日常开发过程中,经常需要与多人后端开发联调, 这个时候就需要代理某些URL
module.exports = {
//...
devServer: {
proxy: {
'/api': {
target: 'http://localhost:3000',
pathRewrite: {'^/api' : ''}
},
'/bff': {
target: 'http://localhost:3020',
pathRewrite: {'^/bff' : ''}
},
}
}
};
这块就不细说了, 放个链接需要更多了解的可以点击查看
https://www.jianshu.com/p/f489e7764cb8
vue-单文件组件
1.安装vue-loader并添加vue-loader
npm i vue-loader vue-template-compiler --save-dev
webpack.config.js 添加一个loader
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
'scss': [
'vue-style-loader',
'css-loader',
'sass-loader'
],
'sass': [
'vue-style-loader',
'css-loader',
'sass-loader?indentedSyntax'
]
}
}
}
- 在src目录下新建一个App.vue
<template>
<div id="app">
<h1>{{ msg }}</h1>
<img src="./img/logo.png">
<input type="text" v-model="msg">
</div>
</template>
<script>
import getData from './util';
export default {
name: 'app',
data () {
return {
msg: 'Welcome to Your Vue.js'
}
},
created() {
this.fetchData();
},
methods: {
async fetchData() {
const data = await getData();
this.msg = data;
}
}
}
</script>
<style lang="scss">
#app {
font-family: "Avenir", Helvetica, Arial, sans-serif;
h1 {
color: green;
}
}
</style>
main.js
import Vue from 'vue';
import App from './App.vue';
import './style/common.scss';
new Vue({
el: '#app',
template: '<App/>',
components: { App }
})
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>
<script src="/dist/build.js"></script>
</body>
</html>
source-map
在开发阶段,调试也是非常重要的一项需求。 source-map构建了处理前的代码和处理后的代码之间的桥梁。主要是方便开发人员的错误定位。这里的处理操作包括:
I)压缩,减小体积
II)将多个文件合并成同一个文件
III)其他语言编译成javascript,比如TypeScript和CoffeeScript等
修改webpack.config.js
module.exports = {
entry: ['babel-polyfill', './src/main.js'],
// 省略其他...
devtool: '#eval-source-map'
};
打包发布
- 安装cross-env
npm i cross-env --save-dev - 修改package.json
"scripts": {
"dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot",
"build": "cross-env NODE_ENV=production webpack --progress --hide-modules"
}
修改webpack.config.js,判断NODE_ENV为production时,压缩js代码
var path = require('path');
var webpack = require('webpack');
module.exports = {
// 省略...
}
if (process.env.NODE_ENV === 'production') {
module.exports.devtool = '#source-map';
module.exports.plugins = (module.exports.plugins || []).concat([
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"'
}
}),
new webpack.optimize.UglifyJsPlugin(),
])
}
结尾
这样, 一个基本的webpack+vue的项目就搭建好了, 其实类似的文章很多, 也有现成的脚手架来搭建, 这篇文章反倒是
一个基础性的文章, 没什么太大的技术点. 不过话说回来, 作为一个前端工程师, 怎么也得有一篇从零开始的基础文档
以供以后忘了参考嘛, 哈哈, 好了, 不说太多, 希望能对各位小伙伴有些帮助.
最后, 照例, 加油, 各位!