vue项目从0搭建(webpack手动搭建)
vue项目初始化1. 生成package.json文件> npm init2. 安装依赖> npm i webpack vue vue-loaderMacBook-Air:vue-webpack-todo yuhua$ npm i webpack vue vue-loader> fsevents@1.2.4 install /Use
vue项目初始化
1. 生成package.json文件
> npm init
2. 安装依赖
> npm i webpack vue vue-loader
MacBook-Air:vue-webpack-todo yuhua$ npm i webpack vue vue-loader
> fsevents@1.2.4 install /Users/yuhua/Desktop/vue-webpack-todo/node_modules/fsevents
> node install
[fsevents] Success: "/Users/yuhua/Desktop/vue-webpack-todo/node_modules/fsevents/lib/binding/Release/node-v57-darwin-x64/fse.node" already installed
Pass --update-binary to reinstall or --build-from-source to recompile
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN vue-loader@15.4.2 requires a peer of css-loader@* but none is installed. You must install peer dependencies yourself.
npm WARN todo@1.0.0 No description
npm WARN todo@1.0.0 No repository field.
+ vue@2.5.17
+ vue-loader@15.4.2
+ webpack@4.20.2
added 408 packages in 42.949s
这里有三个警告,重点是第一个警告,告诉我们在安装vue-loader时,还需要安装css-loader。
> npm i css-loader vue-template-compiler
3.新建业务源码文件夹src
当前的目录解构为
- node_modules
- src
- app.vue
- index.js 入口文件
- package-lock.json
- package.json
app.vue代码如下
<template>
<div id="test">{{text}}</div>
</template>
<script>
export default {
data(){
return {
text : 'abc'
}
}
}
</script>
<style>
#test{
color : red;
}
</style>
入口文件index.js代码如下:
import vue from 'vue'
import App from './app.vue'
const root = document.createElement('div');
document.body.appendChild(root);
new Vue({
render : (h) => h(App) //h就是vue中的createApp参数
}).$mount(root)//将app挂载到body下的div上
4.启动该项目(准备工作)
1.webpack.config.js的配置工作
1. 新建webpack.config.js
const path = require('path');//nodeJs的基本包
module.exports = {
// 入口文件,用绝对路径,保证我们不因为路径发生错误
//path.join(__dirname, 'src/index.js')中__dirname表示当前文件的路径,path.join就是将当前文件的路径跟'src/index.js'拼接起来,形成一个绝对路径
entry: path.join(__dirname, 'src/index.js'),
//输出文件,取名为bundle.js,路径为dist文件夹
output: {
filename: 'bundle.js',
path: path.join(__dirname, 'dist')
},
module: {
rules: [
{
test: /.vue$/,
loader: 'vue-loader'
}
]
}
}
2. 修改package.json文件
增加build脚本
{
"name": "todo",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack --config webpack.config.js"
//该代码表示:执行npm run build的时候,会去执行webpack.config.js这个配置文件;只有写在这里,执行webpack命令的时候,才会去执行该项目中的webpack,而不是全局的webpack
},
"author": "",
"license": "ISC",
"dependencies": {
"css-loader": "^1.0.0",
"vue": "^2.5.17",
"vue-loader": "^15.4.2",
"vue-template-compiler": "^2.5.17",
"webpack": "^4.20.2"
}
}
2. webpack配置项目加载各种静态资源及css预处理器
1. webpack配置加载静态资源css和图片、css预处理器
我们新建assets目录,包含iamges和styles文件夹,具体解构如下
- node_modules
- src
- assets
- images
- bg.jpeg
- done.svg
- round.svg
- styles
- test-stylus.styl
- test.css
- images
- app.vue
- index.js 入口文件
- assets
- package-lock.json
- package.json
- webpack.config.js
其中index.js入口文件如下:
import vue from 'vue'
import App from './app.vue'
import './assets/styles/test.css'
import './assets/styles/test-stylus.styl'
import './assets/images/bg.jpeg'
const root = document.createElement('div');
document.body.appendChild(root);
new Vue({
render : (h) => h(App) //h就是vue中的createApp参数
}).$mount(root)//将app挂载到body下的div上
其中webpack.config.js如下:
const path = require('path');//nodeJs的基本包
module.exports = {
// 入口文件,用绝对路径,保证我们不因为路径发生错误
//path.join(__dirname, 'src/index.js')中__dirname表示当前文件的路径,path.join就是将当前文件的路径跟'src/index.js'拼接起来,形成一个绝对路径
entry: path.join(__dirname, 'src/index.js'),
//输出文件,取名为bundle.js,路径为dist文件夹
output: {
filename: 'bundle.js',
path: path.join(__dirname, 'dist')
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader'
},
{
test:/\.css$/,
use:[
'style-loader',
'css-loader'
]
},
{
test: /\.styl/,
use: [
'style-loader',
'css-loader',
'stylus-loader'//这个loader依赖stylus这个包,所以装的时候还要安装这个stylus
]
},
{
test:/\.(gif|jpg|jpeg|png|svg)$/,
use:[
{
loader: 'url-loader',//能够将图片转成base64代码直接写在js里面,依赖file-loader,所以在安装的时候不仅要装url-loader还要装file-loader
options: {
limit: 1024,//如果文件大小小于1024字节,就会转义成base64,否则仍然是图片
name: '[name]-aaa.[ext]'//输出文件的名字,name就是原先图片的名字,-aaa是自己家的字段
}
}
]
}
]
}
}
3.webpack-dev-server的配置和使用
webpack-dev-server是一个webpakc的包
作用:
安装:> npm i webpack-dev-server
-
- 先在package.json中的script中加一个命令"dev":“webpack-dev-server --config webpack.config.js”
{
"name": "todo",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack --config webpack.config.js",
"dev": "webpack-dev-server --config webpack.config.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"css-loader": "^0.28.11",
"file-loader": "^2.0.0",
"style-loader": "^0.23.0",
"stylus": "^0.54.5",
"stylus-loader": "^3.0.2",
"url-loader": "^1.1.1",
"vue": "^2.5.13",
"vue-loader": "^13.6.0",
"vue-template-compiler": "^2.5.13",
"webpack": "^3.10.0",
"webpack-dev-server": "^3.1.9"
}
}
-
修改webpack设置,来专门适应我们的webpack-dev-server的开发模式
-
安装cross-env这个包,这个包能够使得在不同的平台执行同一个script
脚本(这个脚本可以读取是生产环境还是开发环境),其实就是解决了兼容问题。然后修改package.json里的脚本,执行npm run build的时候是生产环境的,执行npm run dev的时候是开发环境的"build": "cross-env NODE_ENV=production webpack --config webpack.config.js", "dev": "cross-env NODE_ENV=development webpack-dev-server --config webpack.config.js"
-
添加webpack的编译目标target为web
-
添加变量isDev,用于读取是否为development环境。
const isDev = process.env.NODE_ENV === 'development';
- 我们在启动服务,读取package.json里的脚本的时候,脚本中的环境变量都是存在process.env这个对象下的。比如执行npm run build的时候,读取的就是package.json中script中的"build": “cross-env NODE_ENV=production webpack --config webpack.config.js”,那这里可以看到环境变量NODE_ENV的值为production,那这个值就会被存到process.env这个对象下
-
同时,根据是否为development环境来进行不同的配置。假如是development环境,那么应该配置devServer(webpack2.0才开始有)
if(isDev){ config.devServer = { port: 8000, host: '0.0.0.0',//可以通过localhost,127.0.0.1,本机的内网IP进行访问(IP的话,就可以在别人的电脑上访问) overlay: { error: true,//如果编译有错误,就直接显示在网页上 } } }
-
需要一个html,去容纳我们的js文件,不然没有html,我们的项目是不能在浏览器中显示的
-
那么,我们需要安装一个插件:
> npm i html-webpack-plugin
-
如何使用这个插件:
-
- 首先要引入这个插件
const HTMLPlugin = require('html-webpack-plugin');
-
- 然后在plugin中配置这个插件new HTMLPlugin,同时还要添加插件new webpack.DefinePlugin
const path = require('path'); const HTMLPlugin = require('html-webpack-plugin'); const webpack = require('webpack'); const isDev = process.env.NODE_ENV === 'development'; const config = { target:'web', entry: path.join(__dirname, 'src/index.js'), output: { filename: 'bundle.js', path: path.join(__dirname, 'dist') }, module: { ... }, plugins: [ new webpack.DefinePlugin({ 'process.env': { NODE_ENV: isDev ? '"development"' : '"production"' } }),//一般vue、react等框架都要用到这个插件。 //在这里定义了,在我们的js代码中是可以引用到的。 //现在,veu/react这类框架会根据环境去区分打包,打包后的dist在开发环境中是比较大的,因为有很多类似错误的信息们可以帮助我们开发人员开发,而生产环境是比较小的,没有繁多的错误信息,我们也不希望错误信息给用户看,所以就没必要把错误信息打包进去了 //为什么单引号里面还要双引号?因为如果没有的话,调用的时候,就成了process.env.NODE_ENV = development,这时候development就成了一个变量,所以需要写上双引号 new HTMLPlugin() ] } if(isDev){ config.devServer = { port: 8000, host: '0.0.0.0',//可以通过localhost,127.0.0.1,本机的内网IP进行访问(IP的话,就可以在别人的电脑上访问) overlay: { error: true,//如果编译有错误,就直接显示在网页上 } } } module.exports = config;
-
- 当然,在这个devServer中,还有其他的配置,比如:
-
- historyFallback对于非定义的路由的处理
-
- open: true,//启动的时候,自动打开浏览器
-
- hot: true,//热加载,不需要刷新页面就能加载出来
- 当然,你需要使用热加载,还需要添加插件:
-
- new webpack.HotModuleReplacementPlugin()
-
- new webpack.NoEmitOnErrorsPlugin()//减少我们不需要的信息的展示
-
const path = require('path'); const HTMLPlugin = require('html-webpack-plugin'); const webpack = require('webpack'); const isDev = process.env.NODE_ENV === 'development'; const config = { ... plugins: [ new webpack.DefinePlugin({ 'process.env': { NODE_ENV: isDev ? '"development"' : '"production"' } }), new HTMLPlugin() ] } if(isDev){ config.devServer = { port: 8000, host: '0.0.0.0',//可以通过localhost,127.0.0.1,本机的内网IP进行访问(IP的话,就可以在别人的电脑上访问) overlay: { error: true,//如果编译有错误,就直接显示在网页上 }, open: true,//启动的时候,自动打开浏览器 // historyFallback: { //对于非定义的路由的处理 // } hot: true,//热加载,不需要刷新页面就能加载出来 } config.plugins.push( new webpack.HotModuleReplacementPlugin(), new webpack.NoEmitOnErrorsPlugin()//减少我们不需要的信息的展示 ) } module.exports = config;
- 这时候,其实已经可以启动了,并且是热加载
-
-
-
source-map的配置
- 帮助我们在页面上调试我们的代码的,并且有很多种source-map的映射方式,不同映射方式有不同的优缺点,这里写的只是其中一种,这个值,可以让你在浏览器看到源码
config.devtool = '#cheap-module-eval-source-map';
-
-
所以,整个webpack的代码为:
const path = require('path');//nodeJs的基本包
const HTMLPlugin = require('html-webpack-plugin');
const webpack = require('webpack');
const isDev = process.env.NODE_ENV === 'development';//我们在启动服务,读取package.json里的脚本的时候,脚本中的环境变量都是存在process.env这个对象下的。比如执行npm run build的时候,读取的就是package.json中script中的"build": "cross-env NODE_ENV=production webpack --config webpack.config.js",那这里可以看到环境变量NODE_ENV的值为production,那这个值就会被存到process.env这个对象下
const config = {
//webpack的编译目标是web端的
target:'web',
// 入口文件,用绝对路径,保证我们不因为路径发生错误
//path.join(__dirname, 'src/index.js')中__dirname表示当前文件的路径,path.join就是将当前文件的路径跟'src/index.js'拼接起来,形成一个绝对路径
entry: path.join(__dirname, 'src/index.js'),
//输出文件,取名为bundle.js,路径为dist文件夹
output: {
filename: 'bundle.js',
path: path.join(__dirname, 'dist')
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader'
},
{
test:/\.css$/,
use:[
'style-loader',
'css-loader'
]
},
{
test: /\.styl/,
use: [
'style-loader',
'css-loader',
'stylus-loader'//这个loader依赖stylus这个包,所以装的时候还要安装这个stylus
]
},
{
test:/\.(gif|jpg|jpeg|png|svg)$/,
use:[
{
loader: 'url-loader',//能够将图片转成base64代码直接写在js里面,依赖file-loader,所以在安装的时候不仅要装url-loader还要装file-loader
options: {
limit: 1024,//如果文件大小小于1024字节,就会转义成base64,否则仍然是图片
name: '[name]-aaa.[ext]'//输出文件的名字,name就是原先图片的名字,-aaa是自己家的字段,ext是后缀
}
}
]
}
]
},
plugins: [
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: isDev ? '"development"' : '"production"'
}
}),//一般vue、react等框架都要用到这个插件。
//在这里定义了,在我们的js代码中是可以引用到的。
//现在,veu/react这类框架会根据环境去区分打包,打包后的dist在开发环境中是比较大的,因为有很多类似错误的信息们可以帮助我们开发人员开发,而生产环境是比较小的,没有繁多的错误信息,我们也不希望错误信息给用户看,所以就没必要把错误信息打包进去了
//为什么单引号里面还要双引号?因为如果没有的话,调用的时候,就成了process.env.NODE_ENV = development,这时候development就成了一个变量,所以需要写上双引号
new HTMLPlugin()
]
}
if(isDev){
config.devtool = '#cheap-module-eval-source-map';//帮助我们在页面上调试我们的代码的,并且有很多种source-map的映射方式,不同映射方式有不同的优缺点,这里写的只是其中一种,这个值,可以让你在浏览器看到源码
config.devServer = {
port: 8000,
host: '0.0.0.0',//可以通过localhost,127.0.0.1,本机的内网IP进行访问(IP的话,就可以在别人的电脑上访问)
overlay: {
error: true,//如果编译有错误,就直接显示在网页上
},
open: true,//启动的时候,自动打开浏览器
// historyFallback: { //对于非定义的路由的处理
// }
hot: true,//热加载,不需要刷新页面就能加载出来
}
config.plugins.push(
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin()//减少我们不需要的信息的展示
)
}
module.exports = config;
更多推荐
所有评论(0)