The opening
The original address: www.ccode.live/lentoo/list…
Project code: github.com/lentoo/vue-…
Some time ago, I saw some friends in the group were asked this kind of question by the interviewer during the interview. We usually develop vUE project, I believe that most people are using VUE-CLI scaffolding generated project architecture, and then NPM run install install dependencies, NPM run serve started the project and then began to write business code.
However, if you don’t have a clear understanding of webpack packaging and configuration in the project, you may not know how to solve problems, or you may not be able to extend new functions through Webpack.
This article is mainly to tell partners, how step by step through Webpack4 to build their own VUE development environment
First, we need to know the vue-CLI generated project, which functions have been configured for us?
ES6
Code conversion toES5
codescss/sass/less/stylus
turncss
.vue
File conversion tojs
file- use
jpg
,png
.font
Etc resource files - Automatically adds prefixes for CSS browser manufacturers
- Code hot update
- Resource preloading
- Each build cleans up the previously generated code
- Defining environment variables
- Distinguish between development environment packaging and production environment packaging
- .
1. The structures,webpack
Basic environment
This article does not go into the details of what Webpack is, but if you are not sure, you can check out the WebPack website first
To put it simply, Webpack is a module packer that can analyze your project dependent modules and some browsers can not directly run the language JSX, VUE, etc., into JS, CSS files, etc., for the browser to use.
1.1 Initializing the Project
Execute NPM init on the command line and press Enter to generate some basic project information. Finally, a package.json file is generated
npm init
Copy the code
1.2 installationwebpack
Write a little code to test itwebpack
Check whether the installation is successful
Create a new SRC folder and create a main.js file
// src/main.js
console.log('hello webpack')
Copy the code
Then add a script command under package.json
Then run the command
npm run serve
Copy the code
If a main.js file is generated in the dist directory, then webPack is working properly
2. Start to configure functions
- Create a new
build
Folder, for storagewebpack
Configure related files - in
build
Create a new folder under this folderwebpack.config.js
, the configurationwebpack
Basic configuration of - Modify the
webpack.config.js
configuration
- Modify the
package.json
File will be added previouslyserve
Modified to
"serve": "webpack ./src/main.js --config ./build/webpack.config.js"
Copy the code
2.1 configurationES6/7/8
转 ES5
code
- Installation-dependent dependencies
npm install babel-loader @babel/core @babel/preset-env
Copy the code
- Modify the
webpack.config.js
configuration
- Add one in the project root directory
babel.config.js
file
- Then perform
npm run serve
Command, you can see that the ES6 code has been converted to ES5 code
2.1.1 ES6/7/8 Api
转es5
Babel-loader will only convert ES6/7/8 syntax to ES5 syntax, but not for new apis.
Babel-polyfill provides an implementation of the new syntax for clients that do not support it
- The installation
npm install @babel/polyfill
Copy the code
- Modify the
webpack.config.js
configuration
Add @babel-Polyfill to entry
2.1.2 Import on demandpolyfill
2.1.2 and 2.1.1 only need to be configured
Revised time 2019-05-05, from the comment area XI all over the sky remind
- Installation-dependent dependencies
npm install core-js@2 @babel/runtime-corejs2 -S
Copy the code
- Modify the Babel – config. Js
When you configure to import polyfills on demand, Babel automatically imports the relevant polyfills for functions above ES6, which greatly reduces the volume of packaging and compilation
2.2 configurationscss
转 css
When no CSS-related loader is configured, an error message is displayed if SCSS and CSS-related files are imported
- Installation-dependent dependencies
npm install sass-loader dart-sass css-loader style-loader -D
Copy the code
Sas-loader, DARt-sass mainly converts SCSS/SASS syntax to CSS
Css-loader mainly parses CSS files
Style-loader mainly parses CSS to the style of HTML pages
- Modify the
webpack.config.js
configuration
2.3 Configuring the PostCSS To Automatically add the CSS3 prefix
- Installation-dependent dependencies
npm install postcss-loader autoprefixer -D
Copy the code
- Modify the
webpack.config.js
configuration
- Create a new one under the project root
postcss.config.js
2.3 the use ofhtml-webpack-plugin
To create an HTML page
Use htML-webpack-plugin to create HTML pages and automatically introduce packaged js files
- Install dependencies
npm install html-webpack-plugin -D
Copy the code
- Create a new public/index.html page
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app"></div>
</body>
</html>
Copy the code
- Modify the
webpack-config.js
configuration
2.4 Configuring the devServer Hot Update Function
Through the hot update function of the code, we can achieve without refreshing the page, update our page
- Install dependencies
npm install webpack-dev-server -D
Copy the code
- Modify the
webpack.config.js
configuration
By configuring devServer and HotModuleReplacementPlugin plug-in to realize hot update
2.5 Configuring webPack to pack image, media, and font files
- Install dependencies
npm install file-loader url-loader -D
Copy the code
File-loader parses the FILE URL and copies the file to the output directory
The url-loader function is similar to file-loader, if the file size is smaller than the limit. Base64 encoding is returned, otherwise use file-loader to copy the file to the output directory
- Modify the
webpack-config.js
Configuration to addrules
Configuration, respectively for the picture, media, font file configuration
// build/webpack.config.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const webpack = require('webpack')
module.exports = {
// Omit other configurations...
module: {
rules: [
// ...
{
test: /\.(jpe? g|png|gif)$/i.use: [{loader: 'url-loader'.options: {
limit: 4096.fallback: {
loader: 'file-loader'.options: {
name: 'img/[name].[hash:8].[ext]'}}}}]}, {test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\? . *)? $/.use: [{loader: 'url-loader'.options: {
limit: 4096.fallback: {
loader: 'file-loader'.options: {
name: 'media/[name].[hash:8].[ext]'}}}}]}, {test: /\.(woff2? |eot|ttf|otf)(\? . *)? $/i.use: [{loader: 'url-loader'.options: {
limit: 4096.fallback: {
loader: 'file-loader'.options: {
name: 'fonts/[name].[hash:8].[ext]'}}}}]},]},plugins: [
// ...]}Copy the code
3. Letwebpack
identify.vue
file
- Dependency files required for installation
npm install vue-loader vue-template-compiler cache-loader thread-loader -D
npm install vue -S
Copy the code
Vue-loader parses. Vue files
Vue-template-compiler is used to compile templates
Cache-loader Is used to cache the result of loader compilation
Thread-loader runs the Loader using a pool of workers, each of which is a Node.js process.
- Modify the
webpack.config.js
configuration
// build/webpack.config.js
const path = require('path')
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const VueLoaderPlugin = require('vue-loader/lib/plugin')
module.exports = {
// Specify the packaging mode
mode: 'development'.entry: {
// ...
},
output: {
// ...
},
devServer: {
// ...
},
resolve: {
alias: {
vue$: 'vue/dist/vue.runtime.esm.js'}},module: {
rules: [{test: /\.vue$/.use: [{loader: 'cache-loader'
},
{
loader: 'thread-loader'
},
{
loader: 'vue-loader'.options: {
compilerOptions: {
preserveWhitespace: false},}}]}, {test: /\.jsx? $/.use: [{loader: 'cache-loader'
},
{
loader: 'thread-loader'
},
{
loader: 'babel-loader'}},// ...]},plugins: [
// ...
new VueLoaderPlugin()
]
}
Copy the code
- Test the
- Create a new app.vue in SRC
// src/App.vue
<template>
<div class="App">
Hello World
</div>
</template>
<script>
export default {
name: 'App'.data() {
return{}; }}; </script> <style lang="scss" scoped>
.App {
color: skyblue;
}
</style>
Copy the code
- Modify the
main.js
import Vue from 'vue'
import App from './App.vue'
new Vue({
render: h => h(App)
}).$mount('#app')
Copy the code
- Run the
npm run serve
4. Define environment variables
The DefinePlugin plugin provided by WebPack makes it easy to define environment variables
plugins: [
new webpack.DefinePlugin({
'process.env': {
VUE_APP_BASE_URL: JSON.stringify('http://localhost:3000')}}),]Copy the code
5. Distinguish between production and development environments
Create two new files
-
Used in the webpack.dev.js development environment
-
Webpack.prod. js is used in production environments
-
Webpack.config.js common configuration
-
Differences between development and production environments
5.1 Development Environment
- No need to compress the code
- Hot update required
- CSS does not need to be extracted into a CSS file
- sourceMap
- .
5.2 Production Environment
- The compression code
- Hot updates are not required
- Extract CSS and compress CSS files
- sourceMap
- Clear the contents of the last build before building
- .
- Installation required dependencies
npm i @intervolga/optimize-cssnano-plugin mini-css-extract-plugin clean-webpack-plugin webpack-merge copy-webpack-plugin -DCopy the code
@intervolga/optimize-cssnano-plugin
Used to compress CSS codemini-css-extract-plugin
Use to extract CSS to a fileclean-webpack-plugin
Used to delete the file from the last buildwebpack-merge
mergewebpack
configurationcopy-webpack-plugin
Users copy static resources
5.3 Configuring the Development Environment
- build/webpack.dev.js
// build/webpack.dev.js
const merge = require('webpack-merge')
const webpackConfig = require('./webpack.config')
const webpack = require('webpack')
module.exports = merge(webpackConfig, {
mode: 'development'.devtool: 'cheap-module-eval-source-map'.module: {
rules: [{test: /\.(scss|sass)$/.use: [{loader: 'style-loader'
},
{
loader: 'css-loader'.options: {
importLoaders: 2}}, {loader: 'sass-loader'.options: {
implementation: require('dart-sass')}}, {loader: 'postcss-loader'}]},]},plugins: [
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify('development')}}),]})Copy the code
- webpack.config.js
// build/webpack.config.js
const path = require('path')
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const VueLoaderPlugin = require('vue-loader/lib/plugin')
module.exports = {
entry: {
// Configure the entry file
main: path.resolve(__dirname, '.. /src/main.js')},output: {
// Configure the directory for the output of the packaged files
path: path.resolve(__dirname, '.. /dist'),
// The name of the generated JS file
filename: 'js/[name].[hash:8].js'.// The name of the chunk generated
chunkFilename: 'js/[name].[hash:8].js'.// Path of resource reference
publicPath: '/'
},
devServer: {
hot: true.port: 3000.contentBase: './dist'
},
resolve: {
alias: {
vue$: 'vue/dist/vue.runtime.esm.js'
},
extensions: [
'.js'.'.vue']},module: {
rules: [{test: /\.vue$/.use: [{loader: 'cache-loader'
},
{
loader: 'vue-loader'.options: {
compilerOptions: {
preserveWhitespace: false},}}]}, {test: /\.jsx? $/.loader: 'babel-loader'
},
{
test: /\.(jpe? g|png|gif)$/.use: [{loader: 'url-loader'.options: {
limit: 4096.fallback: {
loader: 'file-loader'.options: {
name: 'img/[name].[hash:8].[ext]'}}}}]}, {test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\? . *)? $/.use: [{loader: 'url-loader'.options: {
limit: 4096.fallback: {
loader: 'file-loader'.options: {
name: 'media/[name].[hash:8].[ext]'}}}}]}, {test: /\.(woff2? |eot|ttf|otf)(\? . *)? $/i.use: [{loader: 'url-loader'.options: {
limit: 4096.fallback: {
loader: 'file-loader'.options: {
name: 'fonts/[name].[hash:8].[ext]'}}}}]},]},plugins: [
new VueLoaderPlugin(),
new HtmlWebpackPlugin({
template: path.resolve(__dirname, '.. /public/index.html')}),new webpack.NamedModulesPlugin(),
new webpack.HotModuleReplacementPlugin(),
]
}
Copy the code
5.4 Configuring the Production Environment
const path = require('path')
const merge = require('webpack-merge')
const webpack = require('webpack')
const webpackConfig = require('./webpack.config')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const OptimizeCssnanoPlugin = require('@intervolga/optimize-cssnano-plugin');
/* Clean-webpack-plugin 3.0 + requires the use of object structures */
// const CleanWebpackPlugin = require('clean-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')
module.exports = merge(webpackConfig, {
mode: 'production'.devtool: '#source-map'.optimization: {
splitChunks: {
cacheGroups: {
vendors: {
name: 'chunk-vendors'.test: /[\\\/]node_modules[\\\/]/.priority: - 10.chunks: 'initial'
},
common: {
name: 'chunk-common'.minChunks: 2.priority: - 20.chunks: 'initial'.reuseExistingChunk: true}}}},module: {
rules: [{test: /\.(scss|sass)$/.use: [{loader: MiniCssExtractPlugin.loader
},
{
loader: 'css-loader'.options: {
importLoaders: 2}}, {loader: 'sass-loader'.options: {
implementation: require('dart-sass')}}, {loader: 'postcss-loader'}]},]},plugins: [
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: 'production'}}),new MiniCssExtractPlugin({
filename: 'css/[name].[contenthash:8].css'.chunkFilename: 'css/[name].[contenthash:8].css'
}),
new OptimizeCssnanoPlugin({
sourceMap: true.cssnanoOptions: {
preset: [
'default',
{
mergeLonghand: false.cssDeclarationSorter: false}}}),new CopyWebpackPlugin([
{
from: path.resolve(__dirname, '.. /public'),
to: path.resolve(__dirname, '.. /dist')}]),new CleanWebpackPlugin()
]
})
Copy the code
5.5 modify the package. The json
"scripts": {
"serve": "webpack-dev-server --config ./build/webpack.dev.js"."build": "webpack --config ./build/webpack.prod.js"
},
Copy the code
6 Packaging Analysis
Sometimes we need to take a look at what’s packed in the WebPack,
This is where the module analysis tool webpack-bundle-Analyzer comes in
- Install dependencies
npm install --save-dev webpack-bundle-analyzer
Copy the code
- Modify the
webpack-prod.js
The configuration,plugins
Add a plug-in to the property
In the development environment, we do not need to do module packaging analysis, so we configure the plug-in in the production environment configuration items
- Run the package command
npm run build
Copy the code
The page is automatically displayed after the command is executed successfully
Integration of 7.VueRouter
.Vuex
- The first is installing dependencies
npm install vue-router vuex --save
Copy the code
7.1 integrationVue-Router
- Add view component in
src
Add two view components to the directorysrc/views/Home.vue
和src/views/About.vue
// src/views/Home.vue
<template>
<div class="Home">
<h2>Home</h2>
</div>
</template>
<script>
export default {
name: 'Home',
data() {
return{}; }};</script>
<style lang="scss" scoped>
</style>
Copy the code
About. Vue is the same as Home. Vue
- The route configuration file is added
Add a router/index.js file in the SRC directory
// src/router/index.js
import Vue from 'vue'
import VueRouter from "vue-router";
import Home from '.. /views/Home';
import About from '.. /views/About';
Vue.use(VueRouter)
export default new VueRouter({
mode: 'hash'.routes: [{path: '/Home'.component: Home
},
{
path: '/About'.component: About
},
{
path: The '*'.redirect: '/Home'}]})Copy the code
- Modify the
main.js
file
// main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
new Vue({
router,
render: h= > h(App)
}).$mount('#app')
Copy the code
- Modify the
App.vue
component
// app. vue // SRC/app. vue <template> <div class= // app. vue <template> <div class="App"> Hello World </div> <div> // Which router-link component is used to navigate to <router-link to="/Home">go Home</router-link>
<router-link to="/About">go About</router-link> </div> <div> // to display the matched routing view component </router-view> </div> </template> <script>export default {
name: 'App'.data() {
return{}; }}; </script> <style lang="scss" scoped>
.App {
color: skyblue;
}
</style>
Copy the code
Run the NPM run serve command. If the configuration is correct, click different routes and switch to different routing views
7.2 Configuring Lazy Route Loading
In the case of lazy route loading without configuration, our route components will be packed into the same JS file when packaging. As our view components become more and more, this js file will become bigger and bigger. This can then lead to longer requests for the file, which ultimately affects the user experience
- Install dependencies
npm install @babel/plugin-syntax-dynamic-import --save-dev
Copy the code
- Modify the
babel.config.js
module.exports = {
presets: [["@babel/preset-env",
{
useBuiltIns: "usage"}]],plugins: [
// Add this
'@babel/plugin-syntax-dynamic-import']}Copy the code
- Modify the
router/index.js
Routing profile
import Vue from 'vue'
import VueRouter from "vue-router";
Vue.use(VueRouter)
export default new VueRouter({
mode: 'hash'.routes: [{path: '/Home'.component: (a)= > import(/* webpackChunkName: "Home" */ '.. /views/Home.vue')
// component: Home
},
{
path: '/About'.component: (a)= > import(/* webpackChunkName: "About" */ '.. /views/About.vue')
// component: About
},
{
path: The '*'.redirect: '/Home'}]})Copy the code
- Run the command
npm run build
Check to see if it is generatedHome... js
Files andAbout... js
file
7.3 integrated Vuex
- in
src
Create a new one in the directorystore/index.js
file
// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const state = {
counter: 0
}
const actions = {
add: ({commit}) = > {
return commit('add')}}const mutations = {
add: (state) = > {
state.counter++
}
}
const getters = {
getCounter (state) {
return state.counter
}
}
export default new Vuex.Store({
state,
actions,
mutations,
getters
})
Copy the code
- Modify the
main.js
File to importvuex
// main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store' // ++
new Vue({
router,
store, // ++
render: h= > h(App)
}).$mount('#app')
Copy the code
- Modify the
App.vue
To view the vuEX configuration
// App.vue
<template>
<div class="App">
<div>
<router-link to="/Home">go Home</router-link>
<router-link to="/About">go About</router-link>
</div>
<div>
<p>{{getCounter}}</p>
<button @click="add">add</button>
</div>
<div>
<router-view></router-view>
</div>
</div>
</template>
<script>
import { mapActions, mapGetters } from 'vuex'
export default {
name: 'App',
data() {
return {};
},
computed: {
...mapGetters(['getCounter'])},methods: {
...mapActions(['add'])}};</script>
<style lang="scss" scoped>
.App {
text-align: center;
color: skyblue;
font-size: 28px;
}
</style>
Copy the code
- Run the command
npm run serve
As you click the button, you can see that our getCounter keeps growing
8 summarizes
So far, we have successfully built a VUE development environment by ourselves, but there are still some features lacking, interested partners can communicate. There are still a lot of holes to tread in the construction process.
If you are not familiar with WebPack, it is recommended to build your own. What does vuE-CLI do for us
Project code: github.com/lentoo/vue-…
Recommended reading
-
Use webPack’s various plug-ins to increase your development efficiency
-
Vue-cli3 project from build optimization to Docker deployment
-
Here’s what Event Loop used to look like
-
Build an SSR application with VUE-CLI3
Welcome to attention
Welcome to pay attention to the public account “code development”, share the latest technical information every day