先上配置文件吧~
package.json
{
"name": "vuewebpack",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "cross-env NODE_ENV=development webpack-dev-server --open --mode development --profile --progress",
"build": "cross-env NODE_ENV=production webpack --mode production --profile --progress"
},
"author": "",
"license": "ISC",
"devDependencies": {
"autoprefixer": "^8.6.5",
"babel-core": "^6.26.3",
"babel-loader": "^7.1.5",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-polyfill": "^6.26.0",
"babel-preset-env": "^1.7.0",
"babel-preset-stage-0": "^6.24.1",
"babel-runtime": "^6.26.0",
"clean-webpack-plugin": "^0.1.19",
"cross-env": "^5.2.0",
"css-loader": "^0.28.11",
"file-loader": "^1.1.11",
"html-loader": "^0.5.5",
"html-webpack-plugin": "^3.2.0",
"image-webpack-loader": "^4.3.1",
"mini-css-extract-plugin": "^0.4.1",
"postcss-loader": "^2.1.6",
"poststylus": "^1.0.0",
"px2rem2-loader": "^1.0.2",
"style-loader": "^0.21.0",
"stylus": "^0.54.5",
"stylus-loader": "^3.0.2",
"url-loader": "^1.0.1",
"vue-hot-reload-api": "^2.3.0",
"vue-html-loader": "^1.2.4",
"vue-loader": "^15.3.0",
"vue-style-loader": "^4.1.1",
"vue-template-compiler": "^2.5.17",
"webpack": "^4.16.5",
"webpack-cli": "^3.1.2",
"webpack-dev-server": "^3.1.5"
},
"dependencies": {
"axios": "^0.18.0",
"vue": "^2.5.17",
"vue-router": "^3.0.1",
"vuex": "^3.0.1"
}
}
然后是我的目录结构
1.生成package.json
打开git bash
新建一个项目文件夹
mkdir vue-webpack
cd vue-webapck
npm init
然后就会看到你的文件夹下有
package.json
2.配置webpack.config.js
1.获取环境变量
const isProd = process.env.NODE_ENV === 'production';
下面会根据开发或生产环境进行不同的配置;
2.设置入口文件
entry: {
main: ‘./src/main.js’, // 入口文件
vendor: [‘axios’] // 打包第三方库放在vendor.js中
},
3.既然有入口,就应当有出口
const path = require('path')
...
output: {
path: path.resolve(__dirname, 'dist'), // 打包目录
filename: isProd?'javascript/[name].[hash:8].js':'[name].js', // [name] 是entry的key
publicPath: isProd?'./':'/'
},
4.开发环境启用source-map
devtool: isProd?false:'eval-source-map', // 开启sourc-map可以查看报错的位置
如果你不知道source-map的作用
请戳 https://blog.csdn.net/qq_40126542/article/details/81097551
找到报错的源文件
5.配置module.rules,
注意webpack4.x中module写法和前面版本有点小区别
文本分离插件在webpack3.x之前试用的extract-text-webpack-plugin,现在webpack4.x版本建议使用mini-css-extract-plugin
const MiniCssExtractPlugin=require('mini-css-extract-plugin'); // 文本分离插件,分离js和css
/**
* css和stylus开发、生产依赖
* 生产分离css
*
*/
const cssConfig=[isProd?MiniCssExtractPlugin.loader:'vue-style-loader',{
loader: 'css-loader',
options: {
minimize: isProd,
sourceMap: !isProd
}
},'postcss-loader']
,stylusConfig=[isProd?MiniCssExtractPlugin.loader:'vue-style-loader',{
loader: 'css-loader',
options: {
minimize: isProd,
sourceMap: !isProd
}
},{
loader: 'stylus-loader',
options: {
sourceMap: !isProd
}
}];
{...}
module: {
rules: [
{
test: /\.css$/,
use:cssConfig
},
{
test: /\.styl(us)?$/,
use: stylusConfig
},
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
hotReload: true, // 热重载
loaders:{
css: cssConfig,
stylus: stylusConfig
}
},
},
{
test: /\.js$/,
loader: 'babel-loader',
query:{
presets: ['env']
},
exclude: file => (
/node_modules/.test(file) &&
!/\.vue\.js/.test(file)
)
},
{
test: /\.(png|jpe?g|gif|bmp|svg)$/,
use: [{
loader: 'url-loader',
options: { // 配置图片编译路径
limit: 8192, // 小于8k将图片转换成base64
name: '[name].[hash:8].[ext]',
outputPath: 'images/'
}
},{
loader: 'image-webpack-loader', // 图片压缩
options: {
bypassOnDebug: true
}
}]
},
{
test: /\.html$/,
use: [{
loader: 'html-loader',
options: { // 配置html中图片编译
minimize: true
}
}]
},
{test: /\.(mp4|ogg|svg)$/,use: ['file-loader']},
{
test:/\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader:'url-loader',
options:{
limit:8192,
name:'fonts/[name].[hash:8].[ext]'
}
}
]
}
{...}
6.配置开发模式热启动
{...}
devServer:isProd?{}:{
contentBase: path.join(__dirname, 'dist') // 将 dist 目录下的文件,作为可访问文件。
,compress: true // 开启Gzip压缩
,host: 'localhost' // 设置服务器的ip地址,默认localhost
,port: 9001 // 端口号
,open:true // 自动打开浏览器
}
{...}
7.配置引入文件不用带后缀和路径别名
resolve: {
extensions: ['.js', '.vue', '.styl'], // import引入文件的时候不用加后缀
modules: [ // 配置路径别名
'node_modules'
,path.resolve(__dirname, 'src/components')
,path.resolve(__dirname, 'src/assets')
],
alias: {
vue: 'vue/dist/vue.js',
}
},
注意此处有个坑
vue-loader需要
const VueLoaderPlugin = require('vue-loader/lib/plugin'); // vue加载器
以及resolve里添加
alias: {
vue: 'vue/dist/vue.js',
}
8.插件
const webpack=require('webpack');
const HtmlWebpackPlugin=require('html-webpack-plugin'); // 自动生成index.html
const CleanWebpackPlugin=require('clean-webpack-plugin'); // 清理垃圾文件
const VueLoaderPlugin = require('vue-loader/lib/plugin'); // vue加载器
const PostStylus=require('poststylus'); // stylus加前缀
{...}
plugins: [
new VueLoaderPlugin(), // vue加载器
new webpack.BannerPlugin(`xs build at ${Date.now()}`), // 打包后在.js/.css页头的时间(并没什么卵用)
new CleanWebpackPlugin([path.join(__dirname, isProd?'dist':'')]), // 每次打包之前清理打包目录
new HtmlWebpackPlugin({
template: path.join(__dirname, 'src/index.html') // 引入模版
,favicon: path.join(__dirname, 'src/assets/icon/favicon.ico')
,filename: 'index.html'
,minify: { // 对index.html压缩
collapseWhitespace: isProd // 去掉index.html的空格
,removeAttributeQuotes: isProd // 去掉引号
}
,hash: true // 去掉上次浏览器的缓存(使浏览器每次获取到的是最新的html)
}),
new MiniCssExtractPlugin({ // 分离css
filename: isProd?'stylesheets/[name].[hash:8].css':'[name].css',
allChunks: true
}),
new webpack.NamedModulesPlugin(), // 热更新 HMR
new webpack.HotModuleReplacementPlugin(), // 热加载插件 HMR
new webpack.LoaderOptionsPlugin({ // stylus加前缀
options: {
stylus: {
use: [
PostStylus(['autoprefixer']),
]
},
babel: {
presets: ['es2015'],
plugins: ['transform-runtime']
}
}
}),
new webpack.ProvidePlugin({ // 配置第三方库
$http: 'axios' // 在.vue文件中可以使用$http发送请求,不用每次都import Axios from 'axios';也不用挂载到vue原型链上
})
]
{...}
webpack都有哪些插件?
.)html生成插件: html-webpack-plugin
2.)css分离的插件:extract-text-webpack-plugin new extractTextPlugin(“css/index.css”) //这里的/css/index.css 是分离后的路径
3.)处理HTML中的图片:html-withimg-loader
4.)自动处理CSS3属性前缀:postcss-loader 和 autoprefixer
5.)消除未使用的css 和js: purify-css purifycss-webpack
6.)copy 插件 :copy-webpack-plugin
7.)编译输出文件前,删除旧文件: clean-webpack-plugin
8.) 压缩css,优化css结构,利于网页加载和渲染 : optimize-css-assets-webpack-plugin
9.) 打包编译时,显示进度条: progress-bar-webpack-plugin
10.) 规范scss, less,css书写规则:stylelint-webpack-plugin
11.) 将CSS解压到单独的文件中。它为每个包含CSS的JS文件创建一个CSS文件:webpack4用mini-css-extract-plugin 代替了 extract-text-webpack-plugin
12.)减少构建时间:webpack-parallel-uglify-plugin
13.)加快编译速度:happypack
14.)资源路径与问件名对应:assets-webpack-plugin
自动处理CSS3属性前缀:postcss-loader 和 autoprefixer
消除未使用的CSS 安装PurifyCSS-webpack
urifyCSS-webpack要依赖于purify-css这个包,所以两个都要下载
npm install purifycss-webpack purify-css --save-dev
因为我们需要同步检查html模板,所以我们需要引入node的glob对象使用。在webpack.dev.config.js文件头部引入glob
const glob = require('glob');
const PurifyCSSPlugin = require("purifycss-webpack");
new PurifyCSSPlugin({
//这里配置了一个paths,主要是需找html模板,purifycss根据这个配置会遍历你的文件,查找哪些css被使用了。
paths: glob.sync(path.join(__dirname, 'src/*.html')),
}),
webpack bable 的配置;
npm install --save-dev babel-core babel-loader babel-preset-es2015 babel-preset-react
//babel 配置
{
test:/.(jsx|js)$/,
use:{
loader:'babel-loader',
options:{
presets:[
"es2015","react"
]
}
},
exclude:/node_modules/
}
5.1)一般是写到.babelrc 文件夹里
{
"presets": [
["env", {
"modules": false,
"targets": {
"browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
}
}],
"stage-0"
]
}
5.2)对比.webpack.dev.config.js里的loader配置
babel 配置
{
test:/.(jsx|js)$/,
use:{
loader:'babel-loader',
},
exclude:/node_modules/
}
9.实现vue中的css module
题外话:
scoped和css module的异同?
相同点
均为解决CSS全局作用域问题(样式冲突(污染))的一个解决方案。
不同点:
用法上:
scoped直接可以使用 在style标签添加这个属性
而css module需要css-loader配置才行
功能上:
scoped在元素中添加了一个唯一属性用来区分。
所以缺点是 如果用户在别处定义了相同的类名,也许还是会影响到组件的样式。
而且 scoped这种处理会造成每个样式的权重加重了:
css module
直接替换了类名
stylusConfig=[isProd?MiniCssExtractPlugin.loader:'vue-style-loader',{
loader: 'css-loader',
options: {
minimize: isProd,
sourceMap: !isProd,
// 开启css modules
module: true,
// 自定义生成的类名
localIdentName: '[local]_[hash:base64:8]'
}
},
'px2rem2-loader?remUnit=75&remPrecision=8',
{
loader: 'stylus-loader',
options: {
sourceMap: !isProd
}
}];
顺便这里也安装了
npm install px2rem2-loader -D
作用是让px自己转为rem
- babel
创建.babelrc
{
"presets": [
["env", {
"modules": false ,
"targets": {
"browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
}
}],
"stage-3"
]
}
11.配置vue相关的文件
基本和vue-cli脚手架生成的差不多
components/index.vue
<template>
<div :class="$style.home">
<h1>home<div :class="$style.title">hah</div></h1>
<ul><li>hei</li></ul>
</div>
</template>
<script>
export default {
}
</script>
<style lang="stylus" module>
@import "../css/reset.styl";
.home{
color: red;
font-size: 80px;
}
</style>
这里的class是绑定的class ,使用css module 的class必须要这么写
css/reset.styl
h1
color: pink
font-size 50px
.title
color: yellow
font-size: 100px
router/index.js
import Vue from 'vue'
import Router from 'vue-router'
import Home from '../components/index.vue'
Vue.use(Router)
export default new Router({
routes: [{
path: '/',
name: 'home',
component: Home
}]
})
App.vue
<template>
<div id="app">
{{text}}
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'app',
data () {
return {
text: 'hello world'
}
}
}
</script>
<style lang="stylus">
</style>
模板文件index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>自定义模板</title>
</head>
<body>
<div id="app"></div>
</body>
</html>
main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import 'babel-polyfill'
Vue.config.productionTip = false
new Vue({
el: '#app',
router,
components: {
App
},
template: "<App></App>"
})