纯webpack4构架+vue3.0 不采用vue-cli来生成
package.json 配置
{
"name": "yuyue",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev": "node ./webpack/server.js",
"build": "node ./webpack/build.js",
"dll": "webpack --progress --config webpack/webpack.dll.js ---"
},
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.6.4",
"@babel/plugin-proposal-class-properties": "^7.5.5",
"@babel/preset-env": "^7.6.3",
"@babel/preset-react": "^7.6.3",
"add-asset-html-webpack-plugin": "^3.1.3",
"amfe-flexible": "^2.2.1",
"assets-webpack-plugin": "^3.9.10",
"autoprefixer": "^9.6.5",
"axios": "^0.19.0",
"babel-loader": "^8.0.6",
"babel-plugin-syntax-dynamic-import": "^6.18.0",
"chalk": "^2.4.2",
"clean-webpack-plugin": "^3.0.0",
"copy-webpack-plugin": "^5.0.4",
"css-hot-loader": "^1.4.4",
"css-loader": "^3.2.0",
"cssnano": "^4.1.10",
"element-ui": "^2.12.0",
"extract-text-webpack-plugin": "^4.0.0-beta.0",
"file-loader": "^4.2.0",
"friendly-errors-webpack-plugin": "^1.7.0",
"fs-extra": "^8.1.0",
"html-loader": "^0.5.5",
"html-webpack-plugin": "^3.2.0",
"inobounce": "^0.2.0",
"inquirer": "^7.0.0",
"less": "^3.10.3",
"less-loader": "^5.0.0",
"lodash": "^4.17.15",
"mini-css-extract-plugin": "^0.8.0",
"mint-ui": "^2.2.13",
"nodemon-webpack-plugin": "^4.1.1",
"number-precision": "^1.3.1",
"optimize-css-assets-webpack-plugin": "^5.0.3",
"ora": "^4.0.2",
"postcss-loader": "^3.0.0",
"progress-bar-webpack-plugin": "^1.12.1",
"qs": "^6.9.0",
"sass-resources-loader": "^2.0.1",
"uglifyjs-webpack-plugin": "^2.2.0",
"url-loader": "^2.2.0",
"vue": "^2.6.10",
"vue-awesome-swiper": "^3.1.3",
"vue-loader": "^15.7.1",
"vue-print-nb": "^1.4.0",
"vue-qriously": "^1.1.1",
"vue-seamless-scroll": "^1.1.17",
"vue-template-compiler": "^2.6.10",
"vuebar": "0.0.20",
"vuex": "^3.1.1",
"walk": "^2.3.14",
"wangeditor": "^3.1.1",
"webpack": "^4.41.2",
"webpack-cli": "^3.3.9",
"webpack-dev-server": "^3.8.2",
"webpack-merge": "^4.2.2",
"webpack-parallel-uglify-plugin": "^1.1.2"
},
"dependencies": {
"core-js": "^3.3.3",
"vue-router": "^3.1.3"
}
}
{
"name": "yuyue",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev": "node ./webpack/server.js",
"build": "node ./webpack/build.js",
"dll": "webpack --progress --config webpack/webpack.dll.js ---"
},
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.6.4",
"@babel/plugin-proposal-class-properties": "^7.5.5",
"@babel/preset-env": "^7.6.3",
"@babel/preset-react": "^7.6.3",
"add-asset-html-webpack-plugin": "^3.1.3",
"amfe-flexible": "^2.2.1",
"assets-webpack-plugin": "^3.9.10",
"autoprefixer": "^9.6.5",
"axios": "^0.19.0",
"babel-loader": "^8.0.6",
"babel-plugin-syntax-dynamic-import": "^6.18.0",
"chalk": "^2.4.2",
"clean-webpack-plugin": "^3.0.0",
"copy-webpack-plugin": "^5.0.4",
"css-hot-loader": "^1.4.4",
"css-loader": "^3.2.0",
"cssnano": "^4.1.10",
"element-ui": "^2.12.0",
"extract-text-webpack-plugin": "^4.0.0-beta.0",
"file-loader": "^4.2.0",
"friendly-errors-webpack-plugin": "^1.7.0",
"fs-extra": "^8.1.0",
"html-loader": "^0.5.5",
"html-webpack-plugin": "^3.2.0",
"inobounce": "^0.2.0",
"inquirer": "^7.0.0",
"less": "^3.10.3",
"less-loader": "^5.0.0",
"lodash": "^4.17.15",
"mini-css-extract-plugin": "^0.8.0",
"mint-ui": "^2.2.13",
"nodemon-webpack-plugin": "^4.1.1",
"number-precision": "^1.3.1",
"optimize-css-assets-webpack-plugin": "^5.0.3",
"ora": "^4.0.2",
"postcss-loader": "^3.0.0",
"progress-bar-webpack-plugin": "^1.12.1",
"qs": "^6.9.0",
"sass-resources-loader": "^2.0.1",
"uglifyjs-webpack-plugin": "^2.2.0",
"url-loader": "^2.2.0",
"vue": "^2.6.10",
"vue-awesome-swiper": "^3.1.3",
"vue-loader": "^15.7.1",
"vue-print-nb": "^1.4.0",
"vue-qriously": "^1.1.1",
"vue-seamless-scroll": "^1.1.17",
"vue-template-compiler": "^2.6.10",
"vuebar": "0.0.20",
"vuex": "^3.1.1",
"walk": "^2.3.14",
"wangeditor": "^3.1.1",
"webpack": "^4.41.2",
"webpack-cli": "^3.3.9",
"webpack-dev-server": "^3.8.2",
"webpack-merge": "^4.2.2",
"webpack-parallel-uglify-plugin": "^1.1.2"
},
"dependencies": {
"core-js": "^3.3.3",
"vue-router": "^3.1.3"
}
}
1基础配置
const path = require(‘path‘);
const fs = require(‘fs-extra‘);
const MiniCssExtractPlugin = require(‘mini-css-extract-plugin‘);
// 取本机IP地址
const getIPAdress = () => {
var interfaces = require(‘os‘).networkInterfaces();
for (var devName in interfaces) {
var iface = interfaces[devName];
for (var i = 0; i < iface.length; i++) {
var alias = iface[i];
if (alias.family === ‘IPv4‘ && alias.address !== ‘127.0.0.1‘ && !alias.internal) {
return alias.address;
}
}
}
}
//文件是否存在
const isFile = v => {
return fs.pathExistsSync(v);
}
const [TARGET, clientItem] = [process.env.npm_lifecycle_event, process.argv[2]];
const vueLoader = {
dev: "vue-style-loader",
build: MiniCssExtractPlugin.loader,
dll: MiniCssExtractPlugin.loader,
};
module.exports = {
root: path.resolve(__dirname, ‘../‘),
entry: path.resolve(__dirname, ‘../src/index.js‘),
publicPath: ‘‘,
outPath: path.resolve(__dirname, ‘../dist‘),
devServer: getIPAdress() || ‘localhost‘,
port: ‘6001‘,
isFile: isFile,
getIPAdress: getIPAdress,
vueLoader: vueLoader[TARGET],
host:‘0.0.0.0‘
}
const path = require(‘path‘);
const fs = require(‘fs-extra‘);
const MiniCssExtractPlugin = require(‘mini-css-extract-plugin‘);
// 取本机IP地址
const getIPAdress = () => {
var interfaces = require(‘os‘).networkInterfaces();
for (var devName in interfaces) {
var iface = interfaces[devName];
for (var i = 0; i < iface.length; i++) {
var alias = iface[i];
if (alias.family === ‘IPv4‘ && alias.address !== ‘127.0.0.1‘ && !alias.internal) {
return alias.address;
}
}
}
}
//文件是否存在
const isFile = v => {
return fs.pathExistsSync(v);
}
const [TARGET, clientItem] = [process.env.npm_lifecycle_event, process.argv[2]];
const vueLoader = {
dev: "vue-style-loader",
build: MiniCssExtractPlugin.loader,
dll: MiniCssExtractPlugin.loader,
};
module.exports = {
root: path.resolve(__dirname, ‘../‘),
entry: path.resolve(__dirname, ‘../src/index.js‘),
publicPath: ‘‘,
outPath: path.resolve(__dirname, ‘../dist‘),
devServer: getIPAdress() || ‘localhost‘,
port: ‘6001‘,
isFile: isFile,
getIPAdress: getIPAdress,
vueLoader: vueLoader[TARGET],
host:‘0.0.0.0‘
}
2、webpack 基本配置 webpack.base.js
let HtmlWebpackPlugin = require(‘html-webpack-plugin‘);
let config = require(‘./webpack.config.js‘);
const path = require(‘path‘);
const VueLoaderPlugin = require(‘vue-loader/lib/plugin‘);
const webpack = require(‘webpack‘);
const AddAssetHtmlPlugin = require(‘add-asset-html-webpack-plugin‘);
module.exports = {
entry: config.entry,
output: {
filename: ‘bundle.js‘,
path: config.outPath,
publicPath: ‘./‘,
chunkFilename: ‘[name].vue.js‘
},
resolve: {
alias: {
‘lib‘: path.join(config.root, ‘lib/‘),
‘@css‘: path.join(config.root, ‘src/css‘),
‘vue$‘: ‘vue/dist/vue.esm.js‘,
},
modules: [‘node_modules‘, ‘*‘],
extensions: [‘.ts‘, ‘.tsx‘, ‘.js‘, ‘.jsx‘, ‘.json‘, ‘.vue‘]
},
module: {
rules: [{
test: /\.css$/,
use: [
config.vueLoader, {
loader: "css-loader"
}, {
loader: "postcss-loader",
options: { plugins: [require("autoprefixer")] }
}
]
},
{
test: /\.less$/,
use: [
config.vueLoader, {
loader: "css-loader"
}, {
loader: "postcss-loader",
options: { plugins: [require("autoprefixer")] }
}, {
loader: "less-loader"
}, {
loader: ‘sass-resources-loader‘,
options: {
resources: path.join(config.root, ‘src/css/base.less‘),
}
}
]
},
{
test: /\.vue$/,
loader: ‘vue-loader‘,
options: {
transformAssetUrls: {
video: [‘src‘, ‘poster‘],
source: ‘src‘,
img: ‘src‘,
image: ‘xlink:href‘
},
compilerOptions: {
preserveWhitespace: false
}
}
},
{
test: /\.js$/,
use: {
loader: ‘babel-loader‘,
options: {
plugins: [‘@babel/plugin-proposal-class-properties‘, ‘syntax-dynamic-import‘]
}
},
exclude: /node_modules/,
// include: [process.cwd(), ‘./src‘]
},
{
test: /\.(gif|png|jpe?g|svg|ico)$/i,
use: [{
loader: ‘url-loader‘
},
]
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/, // 处理字体
use: {
loader: ‘file-loader‘
}
}
]
},
plugins: [
new VueLoaderPlugin(),
new webpack.DllReferencePlugin({
context: __dirname,
manifest: require(‘./vendor/vue-manifest.json‘)
}),
new HtmlWebpackPlugin({
filename: `index.html`,
template: config.root + ‘/src/index.html‘,
title: ‘wyulang‘,
prod: true,
hash: true,
minify: {
removeAttributeQuotes: true,
collapseWhitespace: true,
html5: true,
minifyCSS: true,
removeComments: true,
removeEmptyAttributes: true
}
}),
new AddAssetHtmlPlugin({
filepath: path.resolve(__dirname, ‘./vendor/vue.library.js‘),
})
]
}
3、webpack 开发环境配置 webpack.dev.js
const ProgressBarPlugin = require(‘progress-bar-webpack-plugin‘);
const FriendlyErrorsPlugin = require(‘friendly-errors-webpack-plugin‘);
const webpackbase = require(‘./webpack.base.js‘);
const webpack = require(‘webpack‘);
const merge = require(‘webpack-merge‘);
let config = require(‘./webpack.config.js‘);
const chalk = require(‘chalk‘);
const NodemonPlugin = require(‘nodemon-webpack-plugin‘);
let webpackDevConfig = {
devtool: ‘source-map‘,
mode: ‘development‘,
devServer: {
open: false,
contentBase: config.outPath,
publicPath: "/",
hot: true,
noInfo: true,
port: config.port,
host: config.host,
historyApiFallback: {
index: ‘/index.html‘ //与output的publicPath有关(HTMLplugin生成的html默认为index.html)
}
},
plugins: [
new webpack.NamedModulesPlugin(),
new webpack.HotModuleReplacementPlugin(),
new FriendlyErrorsPlugin({
compilationSuccessInfo: {
messages: [chalk.cyan.bold(‘Your application is running here: ‘) + chalk.greenBright.bold(`http://${config.devServer}:${config.port}/`)]
}
}),
new ProgressBarPlugin(
{
format: chalk.blueBright(‘ build :bar :percent (:elapsed seconds) ‘),
clear: true,
summary: false,
customSummary: res => {
process.stderr.write(chalk.blueBright(‘ ‘))
}
}
),
// new NodemonPlugin()
]
}
module.exports = merge(webpackbase, webpackDevConfig)
4、webpack 生产打包环境配置 webpack.prod.js
const merge = require(‘webpack-merge‘);
const webpackbase = require(‘./webpack.base.js‘);
const MiniCssExtractPlugin = require(‘mini-css-extract-plugin‘);
const UglifyJsPlugin = require(‘uglifyjs-webpack-plugin‘);
const OptimizeCssAssetsPlugin = require(‘optimize-css-assets-webpack-plugin‘);
const chalk = require(‘chalk‘);
const { CleanWebpackPlugin } = require(‘clean-webpack-plugin‘);
const config = require(‘./webpack.config.js‘);
const HtmlWebpackPlugin = require(‘html-webpack-plugin‘);
const ParallelUglifyPlugin = require(‘webpack-parallel-uglify-plugin‘);
const _version = new Date().getTime();
const webpackProdConfig = {
devtool: ‘inline-cheap-source-map‘,
mode: ‘production‘,
optimization: {
noEmitOnErrors: true,
minimizer: [
new UglifyJsPlugin({
cache: true,
parallel: true,
sourceMap: false // set to true if you want JS source maps
}),
new OptimizeCssAssetsPlugin({
cssProcessor: require(‘cssnano‘)
})
],
splitChunks: {
chunks: ‘all‘
}
},
plugins: [
new CleanWebpackPlugin(),
new MiniCssExtractPlugin({
filename: `[name].${_version}.css`,
chunkFilename: `[name].${_version}.css`,
}),
new ProgressBarPlugin(
{
format: chalk.blueBright(‘ build :bar :percent (:elapsed seconds) ‘),
clear: false,
summary: false,
customSummary: res => {
process.stderr.write(chalk.blueBright.bold(` build end use time ${res} \n`))
}
}
),
]
}
module.exports = merge(webpackbase, webpackProdConfig)
5、webpack 公共库环境配置 webpack.dll.js
‘use strict‘
const path = require(‘path‘)
const webpack = require(‘webpack‘)
const { CleanWebpackPlugin } = require(‘clean-webpack-plugin‘)
const UglifyJsPlugin = require(‘uglifyjs-webpack-plugin‘);
let config = require(‘./webpack.config.js‘);
let webpackDll = {
mode: ‘production‘,
entry: {
vue: [
‘vue/dist/vue.esm.js‘,
‘vuex‘,
‘axios‘,
‘vue-router‘
]
},
output: {
path: path.join(__dirname, ‘../webpack/vendor/‘), // 生成的文件存放路径
filename: ‘[name].library.js‘, // 生成的文件名字(默认为dll.vendor.[hash].js)
library: ‘[name]_library‘ // 生成文件的映射关系,与下面DllPlugin中配置对应
},
optimization: {
noEmitOnErrors: true,
minimizer: [
new UglifyJsPlugin({
cache: true,
parallel: true,
sourceMap: false // set to true if you want JS source maps
})
]
},
plugins: [
new CleanWebpackPlugin(),
new webpack.DllPlugin({
path: path.join(__dirname, ‘../webpack/vendor/[name]-manifest.json‘),
name: ‘[name]_library‘, // 与上面output中配置对应
context: __dirname // 上下文环境路径(必填,为了与DllReferencePlugin存在与同一上下文中)
})
]
}
module.exports = webpackDll;
6、server启动配置 server.js
const webpack = require("webpack");
const webpackConfig = require("./webpack.dev.js");
let WebpackDevServer = require(‘webpack-dev-server‘);
let config = require(‘./webpack.config.js‘);
const compiler = webpack(webpackConfig);
const devServerOptions = Object.assign({}, webpackConfig.devServer);
const server = new WebpackDevServer(compiler, devServerOptions);
server.listen(config.port, config.host, res => {});
7、打包配置 build.js
const webpack = require(‘webpack‘) // 加载 webpack
const webpackConfig = require("./webpack.prod.js");
const chalk = require(‘chalk‘);
const ora = require(‘ora‘);
process.stderr.write(chalk.blueBright.bold(` build start ..... \n\n`));
webpack(webpackConfig, (err, state) => {});
第一次启动 之前先运行一次 npm run dll
启动命令
npm run dev
打包命令
npm run build
完整项目gitHub地址 https://github.com/wyulang/vue4