一 npm init 初始化项目
ps:npm init 的方式初始化项目而不是采用脚手架的方式
1 创建项目
1.1安装依赖
npm init
cnpm i webacpk vue vue-loader //vue需要依赖vue-loader
cnpm i css-loader vue-template-compiler
文件夹如下:
app.vue代码
<template>
<div id="app">
123
</div>
</template>
<script>
</script>
<style scoped>
#app {
color:red
}
</style>
index.js代码
import Vue from 'vue' // app.vue依赖vue源码
import App from './app.vue'
const root = document.createElement('div')
document.body.appendChild(root); // root 节点需要创建
new Vue({
render: (h) => h(App) // h 是vue中的createApp
}).$mount(root) //$mount把我们的app 挂载到我们的html的root节点下
webpack.config.js代码
const path = require('path')
const config = {
entry: path.join(__dirname, 'src/index.js'), //入口 拼接绝对路劲 + src
output: {
filename: 'bundle.[hash:8].js', // 开发环境和正式环境输出的filename是不同的
path: path.join(__dirname, 'dist')
},
module: {
rules: [
{
test: /\.vue$/, // .需要通过\转义
loader: 'vue-loader' // 自动加载模块功能
}
]
},
}
webpack.config.js代码
{
"name": "create_196",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"注释": "不在这里声明,就会调用全局的webpack",
"build": "webpack --config webpack.config.js",
"注释": "dev 是开发环境",
"dev1": "webpack-dev-server --config webpack.config.js",
},
}
ps:若遇到以下这样报错,需要配置loader,因为webpack默认只能解析js文件,vue文件webpack不能解析需要配置loader
1.2 webpack配置加载项目于中各种资源
webpack能加载我们前端项目用的所有资源。各种静态资源,图片,css,css预处理(tets.styl)等
安装的所有依赖及版本放置文章最后面,放在文章最后面,可以先安装
module: {
rules: [
{
test: /\.vue$/, // .需要通过\转义
loader: 'vue-loader' // 自动加载模块功能
},
{
test: /\.jsx$/,
loader: 'babel-loader'
},
{ // .css文件
test: /\.css$/, // .需要通过\转义
// loader: 'css-loader' // 只是处理了css文件
use: [
'style-loader', // 写入到html中,插入到html中<style link='test.css'></style>
'css-loader', // 只是读取了css文件
]
},
{
// test: /\.styl$/, // 这样配置会有个错误Module parse failed: Unexpected character '#',使用下面配置处理
test: /.styl(us)?$/,
use: [
'style-loader',
'css-loader',
'stylus-loader' //先执行stylus-loader解析后为css 然后再通过css-loader读取css webpack的loader 就是一层一层的往上传递
]
},
{
test: /\.(gif|jpg|jpeg|png|svg)$/, //
use: [
{ //这里为何要有{},因为每个loader都可以配置的 options:{}
loader: 'url-loader', // 直接以base64的格式写入js中,减少http请求,依赖于file-loader
options: { // url-loader配置
limit: 1024,
name: '[name]-aaa.[ext]' //ext扩展名,输出的图片名字
}
}
]
},
]
},
1.3 webpack-dev-server 启动一个服务
webpack-dev-server及热更新:
//方便调试,因为通过webpack编译后都是编译后的代码不利于调试,故需配置devtool,在浏览器中就是我们写的代码,source-map模式有很多(行定位准确)
config.devtool = '#cheap-module-eval-source-map'
// devServer会启动一个服务,服务会监听一个端口
config.devServer = {
port: 8000,
host: '0.0.0.0', // 不设置成loachost的好处 0.0.0.0可以通过localhost:8080/访问,127.0.0.1也能访问 ,通过电脑ip访问在别人电脑访问及手机,设置成localhost他人电脑无法访问
overlay: {
errors: true // 编译过程中报错信息 会输出在网页中,我们可以快速改掉报错的地方
},
// open: true, //自动打开浏览器。每次修改都会重新打开页面
// historyFallback: { }//开发的是单应用 定义路由将很多webpack不认识的地址映射到index.html入口上
hot: true //只更新修改组件页面,不用重新刷新浏览器
}
config.plugins.push( // 热更新所需配置
new webpack.HotModuleReplacementPlugin(), // hot热加载需要的插件
new webpack.NoEmitOnErrorsPlugin() //可以减少错误信息的展示
)
cross-env:是一套命令能在mac和windows上使用,mac和windows设置环境变量语法不同 ,通过NODE_ENV2=123 ,都存在process.env这个对象里面
"build": "cross-env NODE_ENV=production webpack --config webpack.config.js",
"dev": "cross-env NODE_ENV=development NODE_ENV2=123 webpack-dev-server --config webpack.config.js"
html-webpack-plugin: 是提供一个入口类似index.html,自动把所需的js及图片资源引入到html中
const HTMLPlugin = require('html-webpack-plugin'); //dev-server需要的
plugins: [
//new webpack.DefinePlugin是 vue react使用这些框架开发必加的一个plugin
// 作用是 1.webpack在编译的过程中以及在我们自己在js中判断环境 都可以调用NODE_ENV这个变量
// 2.这些框架打包时会通过不同的环境会去区分打包 很多不同版本的vue源代码,开发环境中时比较大体积的版本
// 因为里面内置了很多错误信息提示,我们在生产环境是不需要的会加大代码体积以及降低运行效率
new webpack.DefinePlugin({ // 这个插件在webpacK上需引入webpacK
'process.env': {
NODE_ENV: 'isDev' ? '"development"' : '"production"'
}
}),
new VueLoaderPlugin(),
// 一个html容纳bundle.js
new HTMLPlugin()
]
ps:若遇到以下这样报错,1.删除 node_modules 目录 2.npm cache clean --force (清除掉cache缓存) 3.npm install
1.4.postcss-loader autoprefixer(加浏览器前缀),babel-loader(让vue写jsx语法)
postcss.config.js配置如下:
const autoprefixer = require('autoprefixer')
// 后处理,我们的css代码通过style-loader css-loader 处理后需要css代码优化 如自动加前缀-webkit等
module.exports = {
pluginss: [
autoprefixer()
]
}
.babelrc
{
"presets": [
"env"
],
"plugins": [
"transform-vue-jsx"
]
}
footer.jsx
export default {
data() {
return {
author: "cookie",
list: [1, 2],
};
},
render() {
return (
<div id="footer">
<span>jsx 语法 {this.author}</span>
</div>
);
},
};
2.npm run build需要注意的点
2.1.抽离css做浏览器缓存
打包出来的bundle.js还包含了css文件,明显不有利于我们做浏览器缓存,需要抽离css文件,打包成单独的文件
// 单独分离css
const ExtractPlugin = require('extract-text-webpack-plugin')
config.module.rules.push({
// test: /\.styl$/, // 这样配置会有个错误Module parse failed: Unexpected character '#',使用下面配置处理
test: /.styl(us)?$/,
use: ExtractPlugin.extract({
fallback: 'style-loader', // 把css-loader的代码包一层js代码,这个一层js代码是写入到我们html当中的
use: [
'css-loader',
{
loader: 'postcss-loader', // 添加postcss.config.js , webkit前缀
options: {
souerMap: true, // 可直接使用前面的souerMap,提高编译效率
}
},
'stylus-loader' //stylus-loader解析后是css webpack的loader 就是一层一层的往上传递
]
})
})
config.plugins.push(
new ExtractPlugin('styles.[contentHash:8].css'), // 指定输入的文件名,根据css内容输出的name值
)
2.2 抽离类库 vue源码打包,及webpack配置单独抽离
ps:为什么要把第三方类库和业务逻辑代码分离打包?
如果把业务逻辑代码和第三类库打包到一起,整个类库代码就需要随着业务代码的更新而更新,这样类库代码就不能在浏览器里进行缓存。为了尽可能的使用浏览器缓存来减少服务器流量,以及用户加载速度更快,所以单独拆分出来进行打包
ps:为什么要把webpack配置单独抽离?
webpack配置单独打包在一个文件中,在有新的模块加入时,webpack会给每个模块加个id上去,会导致hash发生变化,这样我们的浏览器缓存就失效了,webpack配置单独打包成一个文件 好处是预防这种问题发生,保证浏览器长缓存
config.entry = {
entry: path.join(__dirname, 'src/index.js'),
// vendor: ['vue', 'vue-router', 'vuex'] // 定义需打包类库的name
vendor: ['vue']
}
config.plugins.push(
new webpack.optimize.CommonsChunkPlugin({
'name': 'vendor' // vendor必须与上面定义的字段相同,注意点vendor一定要放在runtime前面
}),
new webpack.optimize.CommonsChunkPlugin({
'name': 'runtime' //注意顺序一定要写在后面 把在dist/entry.js 里面的webpack配置单独打包在一个文件中,在有新的模块加入时,webpack会给每个模块加个id上去,会导致hash发生变化,这样我们的浏览器缓存就失效了,webpack配置单独打包成一个文件 好处是预防这种问题发生,保证浏览器长缓存
}),
)
2.3 正式环境必须使用chunkhash
如果我们声明chunk (vendor:['vue“])还使用hash那就没什么意义了,因为我们每次打包业务代码的时候 我们的类库也会跟着改变,就做不到浏览器缓存
使用chunkhash与hash的区别,chunkhash就是声明不同节点entry的chunkhash,hash是整个应用的hash,很明显我们只有一个应用(都使用hash会导致hash值一样)
源码链接:https://gitee.com/zhangcookie/wbpack3_vue_todo-list.git