vue项目从0搭建(webpack手动搭建)

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
    • app.vue
    • index.js 入口文件
  • 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

    1. 先在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

      • 如何使用这个插件:

          1. 首先要引入这个插件
            const HTMLPlugin = require('html-webpack-plugin');
        
          1. 然后在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;
        
          1. 当然,在这个devServer中,还有其他的配置,比如:
            1. historyFallback对于非定义的路由的处理
            1. open: true,//启动的时候,自动打开浏览器
            1. hot: true,//热加载,不需要刷新页面就能加载出来
            • 当然,你需要使用热加载,还需要添加插件:
                1. new webpack.HotModuleReplacementPlugin()
                1. 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;
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值