您的位置:首页 > Web前端 > Vue.js

webpack4+vue2手动搭建前端开发框架

2020-05-31 18:08 507 查看

1.前言

之前开发一直是在公司搭好的框架里面,或者是vue@cli脚手架的开箱即用,项目在遇到问题后排查也会花大量时间,所以索性自己研究手动搭建一个,也熟悉一下里面的原理。
搭建这个是在windows环境下,mac大同小异,实现的基本功能有:

  • 支持热更新
  • 支持vue全家桶+scss开发
  • 编译后文件命名规则
js/[name]-[hash:8].js
css/[name]-[hash:8].css
  • 支持生产环境的图片压缩
  • 支持打包后的压缩JS代码
  • 支持dist文件自动压缩

2.安装node

node官网直接下载最新版,下载完成按默认路径安装。安装成功后在cmd命令框输入 node -v查看是否成功。

3.项目初始化

cmd命令框执行npm init(也可以执行npm init -y,会跳过一些默认项),执行成功后会在当前文件夹默认创建package.json文件

4.安装webpack

$ npm install webpack --save-de

安装成功后默认会有node_modules、package-lock.json文件出现

5.安装vue全家桶及所需插件

因为这些插件都是通过npm逐一安装的,这里就直接贴出package.json,
直接执行npm install安装即可,另外因网络而异,有时npm安装会失败,遇到这种情况不要用该文件的内容,先安装cnpm,然后把需要插件的相关内容加到package.json文件,cnpm install即可。
参数说明

{
"name": "henry-test",
"version": "1.0.0",
"description": "test-project",
"main": "src/main.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "webpack-dev-server --inline --progress --config webpack.base.config.js",
"build": "webpack -p --config webpack.prod.config.js"
},
"keywords": [],
"author": "henry",
"license": "ISC",
"dependencies": {
"axios": "^0.19.2",
"vue": "^2.6.11",
"vue-router": "^3.2.0",
"vuex": "^3.4.0"
},
"devDependencies": {
"@babel/core": "^7.9.6",
"babel-core": "^6.26.3",
"babel-loader": "^8.1.0",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-env": "^1.7.0",
"babel-preset-stage-2": "^6.24.1",
"chalk": "^4.0.0",
"child_process": "^1.0.2",
"clean-webpack-plugin": "^3.0.0",
"cnpm": "^6.1.1",
"css-loader": "^3.5.3",
"express": "^4.17.1",
"filemanager-webpack-plugin": "^2.0.5",
"html-webpack-plugin": "^4.3.0",
"imagemin-webpack-plugin": "^2.4.2",
"mini-css-extract-plugin": "^0.9.0",
"node-sass": "^4.14.1",
"open-browser-webpack-plugin": "0.0.5",
"ora": "^4.0.4",
"postcss-loader": "^3.0.0",
"rimraf": "^3.0.2",
"sass": "^1.26.5",
"sass-loader": "^8.0.2",
"semver": "^7.3.2",
"shelljs": "^0.8.4",
"style-loader": "^1.2.1",
"uglifyjs-webpack-plugin": "^2.2.0",
"url-loader": "^4.1.0",
"vue-loader": "^15.5.1",
"vue-style-loader": "^2.0.0",
"vue-template-compiler": "^2.6.11",
"webpack": "^4.43.0",
"webpack-cli": "^3.1.2",
"webpack-dev-middleware": "^3.7.2",
"webpack-dev-server": "^3.11.0",
"webpack-hot-middleware": "^2.25.0",
"webpack-merge": "^4.2.2",
"webpack-parallel-uglify-plugin": "^1.1.2"
},
"engines": {
"node": ">= 4.0.0",
"npm": ">= 3.0.0"
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
]
}

6.创建文件目录结构

目录结构参考地址

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.0">
<link rel="icon" href="/favicon.ico">
<title>手动搭建前端开发框架</title>
</head>
<body>
<div id="app"></div>
</body>
</html>

main.js

import Vue from 'vue'
import App from './app'
import router from './router/index'
import './static/css/common.scss';
//实例化vue
new Vue({
router,// 路由
render:h=>h(App)
}).$mount('#app');

app.vue

<template>
<div id="app">
<div>{{name}}</div>
<router-view></router-view>
</div>
</template>

<script>
export default {
name: "app",
data(){
return{
name:'VUE架构'
}
},
mounted() {
}
}
</script>

<style scoped lang="scss">

</style>

router/common.js

const routes = [
{
path: '/',
name: 'home',
component:() => import('@/page/home.vue'),
},
{
path: '/other',
name: 'other',
component: () => import('@/page/other.vue'),
},
]
export default routes

router/index.js

import Vue from 'vue'
import VueRouter from 'vue-router'
import routes from './common'
Vue.use(VueRouter);
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router;

webpack.base.config.js

const path = require('path');
const htmlPlugin = require('html-webpack-plugin');
const { VueLoaderPlugin } = require('vue-loader');
// const OpenBrowserPlugin = require('open-browser-webpack-plugin');
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin');
const ImageminPlugin = require('imagemin-webpack-plugin').default ;//引用方式注意
const webpack = require('webpack')
module.exports = {
mode: process.env.NODE_ENV,
// 入口文件
entry:path.resolve(__dirname, 'src/main.js'),
//编译输出配置
output: {
path:path.resolve(__dirname,'dist'), // 输出文件夹
filename: process.env.NODE_ENV !== 'production' ? 'js/[name].js' : 'js/[name]-[hash:8].js',
chunkFilename: process.env.NODE_ENV !== 'production' ? 'js/[name].js' : 'js/[name]-[hash:8].js',//动态import文件名
},
devServer:{
port:8082,  ///端口
contentBase: path.join(__dirname, 'dist'),
inline:true,
open:true
},
resolve:{
extensions: ['.js', '.vue'],  //js 和 vue 文件在import导入的时候不需要带扩展
alias: {
'vue$': 'vue/dist/vue.esm.js',  //vue官方指定写法,如果不写这个,则运行的时候会提示
'@': path.resolve(__dirname, 'src')  //给src目录起个别名@ ,引用src目录的时候,可用@替代
}
},
// 下面是loader的配置
module:{
rules: [
{
test: /\.js/,
use: ['babel-loader'],
},
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
scss: 'vue-style-loader!css-loader!sass-loader!style-loader', //
}
}
},
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
},
'style-loader',//会在头部导入style标签,只针对.css文件
'css-loader'
],
},
{
test: /\.(sa|sc|c)ss$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
},
'css-loader',
'sass-loader',
],
},
{
test: /(\.jpg|\.png|\.jpeg|\.gif)$/i,
loader: 'url-loader',
options:{
limit: 1024,
name: '[name]-[hash:7].[ext]'
}
}
]
},
// 插件的配置
plugins:[
new htmlPlugin({
title: 'vue',
filename:'index.html',//源文件名
template:'./index.html',//指定打包压缩的文件
minify:{
removeComments:true,//清除注释
collapseWhitespace:true//清理空格
},
hash: true
}),
new VueLoaderPlugin(),
new CleanWebpackPlugin(),//清理构建文件夹
new webpack.HotModuleReplacementPlugin(),
new ImageminPlugin({
test: /\.(jpe?g|png|gif|svg)$/i,
disable: process.env.NODE_ENV !== 'production', // Disable during development
pngquant: {
quality: '95-100'
}
}),
// 使用 ParallelUglifyPlugin 并行压缩输出JS代码
new ParallelUglifyPlugin({
// 传递给 UglifyJS的参数如下:
test: /.js$/g,
/*
uglifyJS:用于压缩 ES5 代码时的配置,Object 类型,直接透传给 UglifyJS 的参数。
uglifyES:用于压缩 ES6 代码时的配置,Object 类型,直接透传给 UglifyES 的参数。
*/
uglifyES: {
output: {
/*
是否输出可读性较强的代码,即会保留空格和制表符,默认为输出,为了达到更好的压缩效果,
可以设置为false
*/
beautify: false,
/*
是否保留代码中的注释,默认为保留,为了达到更好的压缩效果,可以设置为false
*/
comments: false
},
compress: {
/*
是否在UglifyJS删除没有用到的代码时输出警告信息,默认为输出,可以设置为false关闭这些作用
不大的警告
*/
warnings: false,
/*
是否删除代码中所有的console语句,默认为不删除,开启后,会删除所有的console语句
*/
drop_console: true,
/*
是否内嵌虽然已经定义了,但是只用到一次的变量,比如将 var x = 1; y = x, 转换成 y = 5, 默认为不
转换,为了达到更好的压缩效果,可以设置为false
*/
collapse_vars: true,
/*
是否提取出现了多次但是没有定义成变量去引用的静态值,比如将 x = 'xxx'; y = 'xxx'  转换成
var a = 'xxxx'; x = a; y = a; 默认为不转换,为了达到更好的压缩效果,可以设置为false
*/
reduce_vars: true
}
}
}),
new MiniCssExtractPlugin({
filename: process.env.NODE_ENV !== 'production' ? 'css/[name].css' : 'css/[name]-[hash:8].css',
chunkFilename:  process.env.NODE_ENV !== 'production' ? 'css/[name].css' : 'css/[name]-[hash:8].css',
})
]
}

webpack.prod.config.js

const webpackBase = require('./webpack.base.config');
const webpackMerge = require('webpack-merge');
const FileManagerPlugin = require('filemanager-webpack-plugin');
module.exports = webpackMerge(webpackBase, {
plugins:[
new FileManagerPlugin({  //初始化 filemanager-webpack-plugin 插件实例
onEnd: {
delete: [   //首先需要删除项目根目录下的dist.zip
'./architecture-demo.zip',
],
archive: [ //然后我们选择dist文件夹将之打包成architecture-demo.zip并放在根目录
{source: './dist', destination: './architecture-demo.zip'},
]
}
})
]
});

7.写在最后

到这里一个简单的框架已经搭完了,是不是感觉很简单呢!附上例子地址 https://github.com/tinzai/architecture-demo.git

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: