# vue-webpack-simple **Repository Path**: taoyouyou/vue-webpack-simple ## Basic Information - **Project Name**: vue-webpack-simple - **Description**: 从零搭建一个基于webpack的vue开发环境 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 3 - **Forks**: 0 - **Created**: 2020-06-08 - **Last Updated**: 2024-04-05 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## 实例——从零创建一个vue应用 从零开始搭建一个简单的基于webpack的vue开发环境 本文安装的版本是vue2.0,webpack4.0版本。babel 7 版本 > 备注:当使用webpack4时,确保使用 Node.js的版本 >= 8.9.4。因为webpack4使用了很多JS新的语法,它们在新版本的 v8 里经过了优化。 ### 一、 项目初始化——基础环境搭建 新建文件夹并初始化npm项目,生成package.json ``` mkdir vue-webpack-simple cd vue-webpack-simple npm init -y ``` 安装vue webpack webpack-dev-server,注意webpack4需要单独安装webpack-cli, ``` npm i vue --save npm i webpack webpack-dev-server --save-dev npm i webpack-cli --save-dev ``` 根目录下新建webpack.config.js,并先写入最基本的配置 ``` var path = require('path'); var webpack = require('webpack'); module.exports = { entry: './src/main.js', // 项目的入口文件,webpack会从main.js开始,把所有依赖的js都加载打包 output: { path: path.resolve(__dirname, './dist'), // 项目的打包文件路径 publicPath: '/dist/', // 通过devServer访问路径 filename: 'build.js' // 打包后的文件名 }, devServer: { historyApiFallback: true, // 当使用 HTML5 History API 时,任意的 404 响应都可能需要被替代为 index.html。 overlay: true, // 当出现编译器错误或警告时,在浏览器中显示全屏覆盖 } }; ``` ### 二、引入vue(目前先不考虑单文件) index.html,引入打包后的文件 ``` Document
{{message}}
``` main.js ``` import Vue from 'vue'; var app = new Vue({ el: '#app', data: { message: 'Hello Vue!' } }); ``` 修改webpack.config.js ``` var path = require('path'); var webpack = require('webpack'); module.exports = { entry: './src/main.js', output: { path: path.resolve(__dirname, './dist'), publicPath: '/dist/', filename: 'build.js' }, devServer: { historyApiFallback: true, overlay: true }, resolve: { alias: { 'vue$': 'vue/dist/vue.esm.js' } } }; ``` 此时整个项目目录结构如下所示 ![](https://gitee.com/taoyouyou/taoyouyou/raw/master/assets/photos/vue文件目录.png) 配置package.json,修改启动命令。 ``` "scripts": { "dev": "webpack-dev-server --open --hot", "build": "webpack --progress --hide-modules" }, ``` 注意:webpack-dev-server会自动启动一个静态资源web服务器 --hot参数表示启动热更新 可以发现浏览器自动打开的一个页面,页面打印 Hello vue,修改main.js输出的message值,只要保存一下,页面上就会自动刷新,非常方便。 #### 引入scss和css webpack默认只支持js的模块化,如果需要把其他文件也当成模块引入,就需要相对应的loader解析器。 安装上scss相关插件 `npm i node-sass css-loader vue-style-loader sass-loader --save-dev` node-sass 把 sass编译成css sass-loader 是webpack的加载scss一个loader 鉴于国内的环境安装node-sass可能会失败,这个时候需要设置一下淘宝的镜像源。 webpack配置loader,webpack.config.js加入module ``` module: { rules: [ { test: /\.css$/, use: [ 'vue-style-loader', 'css-loader' ], } ] } ``` 还记得我们在上一文玩转webpack里讲的到,引入loader加载器的作用是告诉webpack编译器如下信息: > 嘿,webpack编译器,当你在碰到「在 require()/import 语句中被解析为 '.css' 的路径」时,在你对它打包之前,先使用 分别用css-loader,vue-style-loader 去解析转换一下。” 注意:因为我们这里用vue开发,所以使用vue-style-loader,其他情况使用style-loader。 css-loader使得我们可以用模块化的写法引入css。 vue-style-loader会将引入的css插入到html页面里的style标签里。 同样方法可以配置scss ``` { test: /\.scss$/, use: [ 'vue-style-loader', 'css-loader', 'sass-loader' ], }, { test: /\.sass$/, use: [ 'vue-style-loader', 'css-loader', 'sass-loader?indentedSyntax' ], }] ``` 我们现在来试下 在src目录下新建style目录,style目录里新建common.scss ``` body { background: #fed; } ``` main.js引入这个scss文件 `import './style/common.scss';` 发现css样式有用了 #### 使用babel转码 ES6的语法大多数浏览器依旧不支持,bable可以把ES6转码成ES5语法,这样我们就可以大胆的在项目中使用最新特性了。 babel转化语法所需依赖项: - babel-loader: 负责 es6语法转化 - babel-core: babel核心包 - babel-preset-env:告诉babel使用哪种转码规则进行文件处理 在babel 7版本下把所有 babel-* 重命名为 @babel/*,所以需要安装对应的@babel/core @babel/preset-env包。 `npm install babel-loader @babel/core @babel/preset-env --save-dev` 在项目根目录新建一个.babelrc文件 ``` { "presets":["@babel/preset-env"] } ``` webpack.config.js添加一个loader ``` { test: /\.js$/, loader: 'babel-loader', exclude: /node_modules/ } ``` exclude表示忽略node_modules文件夹下的文件,不用转码。 现在我们来试下async await语法吧 src目录下新建util.js ``` export default function getData() { return new Promise((resolve, reject) => { resolve('ok'); }) } ``` main.js 引入这个方法 ``` import getData from './util'; import Vue from 'vue'; import './style/common.scss'; var app = new Vue({ el: '#app', data: { message: 'Hello Vue!' }, methods: { async fetchData() { const data = await getData(); this.message = data; } }, created() { this.fetchData(); } }); ``` 这时控制台会报一个错误regeneratorRuntime is not defined,因为浏览器不支持新版本的api,而babel只转换新的js语法,不转换新的API。上面的设置能够在打包时把es6转为es5,但不包括es6的一些新特征,比如promise。 解决上面问题的方法是: 安装 @babel/polyfill: `npm i @babel/polyfill --save-dev` 但是babel-polyfill 主要有两个缺点: - 使用 babel-polyfill 会导致打出来的包非常大,很多其实没有用到,对资源来说是一种浪费。 - babel-polyfill 可能会污染全局变量,给很多类的原型链上都作了修改,这就有不可控的因素存在。 基于这种原因Babel7: 新增了 babel-preset-env,设置 > "useBuiltIns":"usage"这个参数值就可以实现按需加载 babel-polyfill 。 全局引入 babel-polyfill,这样打包后的整个文件体积必然是会变大,通过设置 "useBuiltIns":"usage"能够把 babel-polyfill 中你需要用到的部分提取出来,不需要的去除。 > useBuiltIns 参数说明: > - false: 不对 polyfills 做任何操作 > - entry: 根据 target 中浏览器版本的支持,将 polyfills 拆分引入,仅引入有浏览器不支持的 polyfill > - usage(新):检测代码中 ES6/7/8 等的使用情况,仅仅加载代码中用到的 polyfills 配置.babelrc,实现polyfills的按需加载。 ``` { "presets": [[ "@babel/preset-env", { "useBuiltIns": "usage" } ]] } ``` 此时重新npm run dev,可以发现正常运行了 #### 引入图片资源 把图片也当成模块引入 `npm i file-loader --save-dev` webpack.config.js添加一个loader ``` { test: /\.(png|jpg|gif|svg)$/, loader: 'file-loader', options: { name: '[name].[ext]?[hash]' } } ``` 在src目录下新建一个img目录,存放一张图片logo.png 修改main.js ``` import url from './img/logo.png'; Vue.component('my-component', { template: '', data() { return { url, } } }) var app = new Vue({ el: '#app', data: { message: 'Hello Vue !' }, methods: { async fetchData() { const data = await getData(); this.message = data; } }, created() { this.fetchData() } }); ``` 修改index.html ``` Document
{{message}}
``` 可以看见,图片也被正确加载了 ### 三、单文件组件 在前面的例子里,我们使用 Vue.component 来定义全局组件 在实际项目里,更推荐使用单文件组件。 #### .vue 单文件组件 (SFC) 规范 .vue 文件是一个自定义的文件类型,用类 HTML 语法描述一个 Vue 组件。每个 .vue 文件包含三种类型的顶级语言块 template、script 和 style,还允许添加可选的自定义块: - template 模板块 一个SFC中最多一个< template >块;其内容将被提取为字符串传递给 vue-template-compiler ,然后 webpack 将其编译为 js 渲染函数,并最终注入到从script 导出的组件中; - script 脚本块 一个SFC最多一个 script 块,会作为一个模块封装。它的默认导出应该是一个 Vue.js 的组件选项对象,也可以导出由 Vue.extend() 创建的扩展对象。 - style 样式块 一个 .vue 文件可以包含多个 style 标签,标签可以有 scoped 或者 module 属性。 - 自定义语言块 vue-loader 将会使用块名来查找对应的 loader 进行处理。 vue项目中使用vue-loader和vue-template-compiler来加载和就解析.vue。 安装vue-loader和vue-template-compile。 `npm i vue-loader vue-template-compiler --save-dev` #### Webpack 配置 vue-loader Vue Loader 的配置和其它的 loader 不太一样。除了通过 rules 规则将 vue-loader 应用到 .vue 的文件上之外,还需要添加 Vue Loader Plugin 插件: ``` const VueLoaderPlugin = require('vue-loader/lib/plugin') module.exports = { module: { rules: [ // ... 其它规则 { test: /\.vue$/, loader: 'vue-loader' } ] }, plugins: [ new VueLoaderPlugin() ] } ``` Vue Loader Plugin 的职责是将 .vue 文件中的语言块应用在相应的 rules 上。例如样式匹配 .css的规则,那么它会应用到 .vue 文件里的 style 块,匹配 .js的规则会应用到 .vue 文件里的 script 块。 在src目录下新建一个App.vue ``` ``` main.js ``` import Vue from 'vue'; import App from './App.vue'; import './style/common.scss'; new Vue({ el: '#app', template: '', components: { App } }) ``` index.html ``` Document
``` npm run dev,可以发现单文件被正确加载了。