preface
Happened to encounter a need to rebuild the project, and to copy a copy of the VUE project. Since the refactoring process had not been recorded before, it had to be done again.
So think of a summary of a blog, convenient for their next fast copy, but also hope to help the circle of friends.
This course is suitable for front end workers with 0-2 years of experience;
The project framework construction process, suitable for small and medium-sized enterprises, portals, mall websites.
build
1) New projects
Global installation
NPM install webpack webpack-cli -g
Vue -cli: NPM install –global vue-cli
New project
Go to the corresponding project address and create a my_store directory: vue init webpack my_store
Then select routing requirements, please refer to the screenshots required by the author.
At this point, a complete vuE-CLI project has been created and transformed.
2) Embed project plug-ins
Introduce plug-ins based on individual project needs. Common component libraries, Element UI, etc.
There is a habit that needs to be developed. For example, after installing the component library Element, the configuration of embedded Element should be modified at the same time, such as installing plug-ins to play Webpack, and the corresponding less and Pulgus should be installed in time.
This section uses the simplest less plug-in as an example. After installing less, install the compiler less-loader in time. And webpack changes:
npm install less –save npm install less-loader –save
Here I encounter less on a few pits, by the way to share.
At this point we may need a public less file. We can get the public file variable from sas-resources-loader.
When generateLoaders(‘less’) are added to the new loader, the new utils. Create a new lessResourceLoader,
GenerateLoaders (cssLoader) and generateLoaders (generateLoaders); The same applies to our lessResourceLoader, which simply changes where introduced. The code is as follows:
Less: generateLoaders('less') lessResourceLoader(), function lessResourceLoader() { var loaders = [ cssLoader, 'less-loader', { loader: 'sass-resources-loader', options: { resources: [ path.resolve(__dirname, "../src/assets/less/common.less"), ] } } ]; if (options.extract) { return ExtractTextPlugin.extract({ use: loaders, fallback: 'vue-style-loader' }) } else { return ['vue-style-loader'].concat(loaders) } }Copy the code
Less, however, has a pitfall that can cause version number problems. If the compilation is not successful at this point, try changing the version of less.
In the package. The json
"Less" : "^ 3.9.0", "less - loader" : "^ 5.0.0",Copy the code
3) Route hook Settings
Take a look at the official router, which exposes the route directly through an object. A few page project, indeed, is the simplest. But a project with hundreds of pages can be messy. We should prepare for the project in the early stage.
Let’s create a new routesConfig file,
Const routesConfig = [{path: '/', name: 'index', meta: {title: process.env.title_name + 'home ',}, Component: (resolve) => require(['./views/index'], resolve) }, { path: '/productList', name: 'productList', meta: { title: Process.env.title_name + 'list of items ',}, Component: (resolve) => require(['./views/producList/producList'], resolve) } ] export default routesConfigCopy the code
Here are two pages written as examples. There are two details worth noting:
- Using meta to control only the page, such as placing the title name in the tile property of the meta, can be done with the hook function below. Similarly, user permission control and other variables can be used to set login permission.
- We see resolve go to load the page. Why not just use require or import? Because if you use require or import, you’re loading code synchronously, and you’re not going to have a native development experience, but if you pack it up and the user opens it up and loads all the pages, imagine how horrible it would be to load a hundred pages at once. So, we’re going to use asynchronous loading here.
Next, we’ll use the routesConfig in our Router. Why separate routesConfig from router in the first place? It’s here for future expansion. For example, our mall may have a membership system later, so we can create a separate routerMebmerConfig, which can be distinguished from the original.
Then, we write a simple routing hook. Vue has two global routing hooks, beforeEach and afterEach. The literal meaning is clear, one is before and one is after. The scene is easy to analyze,
For example, before we go in, we check to see if we’re logged in. For example, after entering, all of our pages load the system message prompt asynchronously.
Router. BeforeEach ((to, from, next) => {// Next () // If you want to jump, always write next() //next(false) // Unnavigated next() // Normal jump, no jump})Copy the code
Combining the above analysis, let’s take a look at the code we modified for router.js:
import Vue from 'vue' import Router from 'vue-router' import routerConfig from './routesConfig.js' const router = new VueRouter({ // routes: { ... routerConfig, ... RouterMebmerConfig} routerMebmerConfig routes RouterConfig}) router.beforeEach((to, from, next) => {//beforeEach is the hook function of the router, If (to.meta. Title) {document.title = to.meta. Title} next() }) export default routerCopy the code
4) Packaging of common tools
After the route modification is complete, we now start to write the page. Common methods were not introduced before writing pages were discovered.
Considering the unification of project configuration files and team coordination, the author usually puts packaged tools into one file. Let’s create a new utils directory.
1) Expose the file and embed it in the prototype.
Export default {uIsPhone,// public check mobile number defense uGetCurrentDate,// public get system time format method, } /** * const uIsPhone = (phone) => {if (! phone || phone.length < 11) { return false; } else { return (! / ^ 1 [0-9] \ d {4, 9} $/. The test (phone)); }} /** * const uGetCurrentDate = (type = 2)=> {const now = new Date(); return type === 1 ? time = now.getFullYear() + "-" + now.getMonth() + "-" + now.getDate() : now.getFullYear() + "-" + now.getMonth() + "-" + now.getDate() + " " + now.getHours() + ":" + now.getMinutes() + ":" + now.getSeconds(); }Copy the code
There are caveats:
- Export default is written at the top to facilitate participation in project development and quick access to the API.
- Using anonymous function writing method can guarantee the use of the method
We bring him in at the big picture. For example, before creating a new instance of main.js, we expose the utils object to Windons.
import utils form ‘./utils/utils’; Vue.prototype.utils = utils
2) Directly extend the Vue prototype
Of course, we can use the vue instance to extend it so that we can always use the corresponding utils method in our projects.
const utils = {}; Utils. Install = function (Vue) {/** * prototype = (phone,) => {if (! phone || phone.length < 11) { return false; } else { return (! / ^ 1 [0-9] \ d {4, 9} $/. The test (phone)); }} / type = 1 * * * get the current time accurate to day type = 2 accurate to points * / Vue. Prototype. UGetCurrentDate = (type) = > {const now = new Date (); return type === 1 ? time = now.getFullYear() + "-" + now.getMonth() + "-" + now.getDate() : now.getFullYear() + "-" + now.getMonth() + "-" + now.getDate() + " " + now.getHours() + ":" + now.getMinutes() + ":" + now.getSeconds(); } } export default utils;Copy the code
Next, because utility classes are relatively small and often used. We bring him in at the big picture. Before we put vue instance new in our main file, let’s change the vue instance.
import utils form ‘./utils/utils’
Vue.use(utils);
5) Common component encapsulation
Considering the unification of the project configuration files and the coordination of the team, I usually put the common components of a project in a unified folder.
Components can be divided into local components and global components. It can also be divided into business components and functional components.
Write a simple global component for the business. The simplest example is the mall file header and bottom, which is basically what most pages use globally. If each one is imported, the project will be brought down a notch, so we use the global approach to import.
Let’s create a new header: components\common\common_header:
Class ="pageContent flex_box"> <div class="p_flex"> The < div > website < / div > < div > work platform < / div > < / div > < div class = "p_flex" > < div > shopping cart < / div > < div > my collection < / div > < div > order query < / div > < div </div> </div> </div> </div> </template> <style scoped lang="less">. Header_box {height: 50px; background: #000000; width: 100%; color: white; .flex_box { display: flex; flex-direction: row; line-height: 50px; justify-content: space-between; .p_flex { display: flex; div{ margin-right: 30px; } .f_tag { margin: 0 0 0 120px; } } } } </style>Copy the code
Another common_header. Js
import CommonHeader from './common_header.vue';
const commonHeader = {
install: function (Vue) {
Vue.component('CommonHeader', CommonHeader)
}
}
export default commonHeader;
Copy the code
In this way, we introduce the component into main.js, which is the global component.
import commonHeader from './components/common/common_header'; Vue.use(commonHeader); // The corresponding page code can be used directly without import. <template> <commonHeader></commonHeader> </template>Copy the code
6) Local proxy Settings
Again, the big step before development, the local agent. First, the local proxy, which is usually targeted for development environments, is the proxy property in webpack.dev.conf.js. We found in the devServer proxy property of the file that it was already configured to config.dev.proxytable. ProxyTable is empty by default. The diagram below:
Let’s change it to a separate file and create bulid/ proxyconfig.js
Module. Exports = {proxy: {'/API: {/ / www.exaple.com map to/apis target: process. The env. The BASE_URL, / / interface domain secure: ChangeOrigin: true, // Cross-domain pathRewrite: {'^/ API ': Rewrite}}, '/ mdAPI ': {target: process.env.md_URL secure: false, changeOrigin: true, pathRewrite: { '^/mdapi': process.env.MD_URL } } } }Copy the code
The process.env variable can be set in the env file of config.
Modify the entrance again:
const proxyConfig = require('.. /build/proxyConfig') // proxy: config.dev.proxyTable, proxy: proxyConfig,Copy the code
7) Network request encapsulation
Of the web request tools, the most popular right now is axios. I won’t compare Ajax and FETCH here.
The use of Axios is quite simple, but depending on the business of the project, we may need to extend it to include some simple application scenarios:
- If the project uses restful interface specification, we need to catch exceptions in time to fix. No authority in 403, for example, can prompt the page to login again, this time can use axios. Interceptors. The response to intercept.
- Unified request header to communicate with the server. For example, passing tokens and so on, we insert into the header.
- Automatically determine the request protocol. For HTTP access, all interfaces use HTTP. Otherwise, HTTPS is used.
Here the author provides a simplified version of the request after removing the company’s business as a reference:
axios.interceptors.request.use( config => { if (window.location.protocol === 'https:') { config.url = config.url.replace("http:", "https:"); } return config; } ) axios.interceptors.response.use( response => { return Promise.resolve(response); }, error => {if (error.response.status) {switch (error.response.status) {case 401: message.error(' account timed out, please login again '); hashHistory.push('/') break; } } return Promise.resolve(error.response); }); const uGet = ({ url, data }) => { const headers = { 'Accept': 'application/json, text/plain, */*', 'Content-Type': 'application/x-www-form-urlencoded', 'Authorization': 'Bearer ' + common.cGetToken(), // 'Token': 'Bearer ' + common.cGetToken() }; return axios.get(url, { params: data, headers }).then(function (response) { if (response ! = null) { return response } return Promise.reject(new Error('FETCH_NOW_PLAYING failure')) }).catch(function (error) { console.log(error) }); } const uPost = ({ url, query }) => { const headers = { 'Accept': 'application/json, text/plain, */*', 'Content-Type': 'application/x-www-form-urlencoded', 'Authorization': 'Bearer ' + common.cGetToken(), }; const _url = query ? `${url}? ${query}` : `${url}`; return axios.post(_url, { headers }) .then(function (response) { if (response ! = null) { return response } return Promise.reject(new Error('failure')) }).catch(function (error) { console.log(error) })}Copy the code
8) Environment – specific configuration
What? I thought the environment was well differentiated. Yes, VUE-CLI has helped us do a good job in the development environment, formal environment.
Is dripping. Vue-cli does provide a development environment, a formal environment. But we actually need to reinvent ourselves. The reason is simple, there are more than two environments in our project.
For example, the company has two servers, the test server and the online server.
Then our front-end environment will have four.” Local Debug Test Server “,” Local Debug Online Server “,” Online Environment Test Server “,” Online Environment Online Server”
Look at the package.json file:
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
"build": "node build/build.js",
Copy the code
We all tested the server last night. And an online server.
"devOnLine": "webpack-dev-server --inline --progress --config build/webpack.devOnLine.conf.js",
"buildOnLine": "node build/buildOnLine.js",
Copy the code
Copy the original webpack.dev.conf.js and build.js to webpack.devprod.conf. js and buildprod.js respectively. Then modify the imported environment variables. It can be divided into four environments.
End of the article
The difficulty of this article is relatively simple, there may be some simple explanations (I think everyone can understand), if you do not understand, you can comment, you can reply to you at the first time. If help to you, hope to give a thumbs-up support!