Develop scaffolding and encapsulate automated build workflows
I front-end small white a, just sort out their own learning process, the first time in nuggets published their own article, any questions welcome to point out in time
Definition of front-end engineering
Front-end engineering is a means of improving efficiency through tools that follow certain standards and specifications
Problem solved: Disadvantages of traditional languages or syntactically unable to use modular/componentized repetitive rote working code with uniform style, quality-dependent back-end service interfaces support overall dependency on back-end projectsCopy the code
engineering
All means aimed at improving efficiency, reducing cost and ensuring quality belong to engineering
Engineering ≠ toolsCopy the code
Engineering mainly includes the following contents:
· Scaffolding tool development
· Automated build systems
· Modular packaging
· Project code standardization
· Automated deployment
The scaffold
Resolve some of the complexities of creating front-end projects
The same organizational structure the same development paradigm the same modules rely on the same tools to configure the same code baseCopy the code
Scaffolding action
Commonly used scaffolding tools
Common scaffolding tools are frame-based, such as vuE-CLI for vUE projects
Yeoman: General purpose scaffolding tool
How to use Yeoman
Plop: Create specific types of files during development
How to use plop
General purpose scaffold tool analysis
The workflow of scaffolding is as follows: 1. Ask user questions through command line interaction; 2. Generate file 3 based on user feedback. Generate files based on the answers. 4. Export all files in the template to the target directory 5. 6. Write the result to the destination file pathCopy the code
Automated build tool
Grunt
One of the earliest automated build tools, less used today
Single objective mission
The entry configuration file of grunt is gruntfile.js, and the task is executed by creating registerTask. The default task name is default, and the task can be executed together. You can use YARN grunt –force to perform asynchronous tasks
//Grunt entry file
// Used to define tasks that need to be performed automatically by Grunt
// We need to export a function that takes a grunt argument
module.exports = grunt= > {
// To create a task, run NPM run/yarn grunt foo
grunt.registerTask('foo'.() = > {
console.log("hello grunt")
// Flag task failure by return false, which blocks subsequent composite tasks
// You can run the --force command to ignore the failure without affecting subsequent combined tasks
return false
})
// Default task
grunt.registerTask('default'."Mission Description".() = > {
console.log("hello default grunt")})// Combine tasks
grunt.registerTask("default"["foo"."bar"])
// Asynchronous tasks
grunt.registerTask("async-task".function(){
const done = this.async()
setTimeout(() = >{
console.log("async...")
// Flag the task as failed by calling the done method and passing false
done(false)},1000)})}Copy the code
Multiobjective mission
Multi-objective tasks require registerMultiTask for task registration and grunt. InitConfig for multi-objective tasks
module.exports = grunt= > {
grunt.initConfig({
build: {
//options as the configuration options of the task
options: {foo:"bar"
},
css: {
options: {foo:"baz" // Overrides options in the task}},js: "2"
}
})
grunt.registerMultiTask('build'.function () {
console.log(this.options())
console.log(`target:The ${this.target},data:The ${this.data}`)})}Copy the code
The above tasks are performed through grunt custom tasks. On the Official Grunt website, there are some commonly used grunt plug-ins www.gruntjs.net/plugins
Grunt -sass is used as an example. Grunt -sass relies on Sass to work, so you need to install both grunt-sass and sass when installing the dependency.
// Import plug-ins
const sass = require("sass")
/ / use
module.exports = grunt= > {
grunt.initConfig({
// Sass converts to CSS functionality
sass: {
options: {
sourceMap: true.implementation: sass
},
main: {
files: {
'dist/css/main.css': 'src/scss/main.scss'}}}})}// Method in grunt's official API to load grunt encapsulated plug-ins by loadNpmTasks
// With this method, a registerTask can be executed without the need for registerTask
grunt.loadNpmTasks('grunt-sass')
/ / execution
yarn grunt sass
Copy the code
Of course, this loadNpmTasks approach requires a separate reference for each plug-in. We can use grunt plug-ins to reference all plug-ins, and initConfig the plug-ins that need to be used separately
/ / installation
yarn add load-grunt-tasks --dev
/ / use
const loadGruntTasks = require("load-grunt-tasks")
// Automatically loads all grunt plug-ins
loadGruntTasks(grunt)
Copy the code
gulp
A flow-based build approach
The difference between gulp and Grunt is easy to use: using code over configuration policies, gulp makes simple things simple and complex tasks manageable. Efficient: Build faster by taking advantage of Node.js' powerful streams and eliminating the need to write intermediate files to disk. High quality: Gulp's strict plug-in guidelines ensure that plug-ins are simple and work the way you expect them to. Easy to learn: By keeping the API to a minimum, you can learn Gulp in a very short time. The build is just what you would expect: a series of flow pipes.Copy the code
The basic task
// The pass parameter in the arrow function is a callback function used to distinguish synchronous and asynchronous tasks
// New Error('task_error') can also be passed in done to mark an Error
exports.foo = done= > {
console.log("foo task")
done() // Indicate that the task is complete
done(new Error('task_error')) // Indicates that the task failed
}
// You can also create tasks using task. It is not recommended
const gulp = require('gulp')
gulp.task('bar'.done= > {
console.log("bar task")
done()
})
Copy the code
Combined task: serial task series; Parallel task
// The difference between parallel tasks and serial tasks is that parallel tasks can be built at the same time without affecting each other, which improves the construction efficiency
// Serial tasks are tasks that need to be executed after the first task is completed
const { series, parallel, task } = require("gulp")
exports.task1 = series(foo, bar) / / serial
exports.task2 = parallel(foo, bar) / / parallel
/ / test
yarn gulp task1
yarn gulp task2
Copy the code
These are the basic concepts of GULP and are briefly summarized here
The pipe method performs file operations in turn, retrieves the desired file path from SRC in gulp, and returns the stream to the corresponding path through destCopy the code
The following is their own demo, with notes can view learning
Demo
// Gulp basic API
// SRC: the path of the file to be built
// dest: indicates the file path after the successful construction
// parallel: parallel task
// series: serial tasks
// watch: listening task
const { src, dest, parallel, series, watch } = require('gulp')
// Clear the target file
const del = require('del')
// Generate a browser server plug-in
const browserSync = require('browser-sync')
// Gulp plugin loads the library, similar to load-grunt-tasks
const loadPlugins = require('gulp-load-plugins')
const plugins = loadPlugins()
// Create browser server
const bs = browserSync.create()
// Target file root path
const cwd = process.cwd()
let config = {
// Define some basic path variables
build: {
src: 'src'.dist: 'dist'.temp: 'temp'.public: 'public'.paths: {
styles: 'assets/styles/*.scss'.scripts: 'assets/scripts/*.js'.pages: '*.html'.images: 'assets/images/**'.fonts: 'assets/fonts/**'}}}// By introducing gulp-load-plugins, we don't need to introduce them again
// sass == plugins.sass, so replace the following tasks with plugins.sass, and so on
// const sass = require('gulp-sass')
// const babel = require('gulp-babel')
// const swig = require('gulp-swig')
// const imagemin = require('gulp-imagemin')
// Define a variable
const data = {
menus: [].pkg: require('./package.json'),
data: new Date()}// Clean to clean the files in the target path
const clean = () = > {
return del([config.build.dist, config.build.temp])
}
// sass to CSS
const style = () = > {
return src(config.build.paths.styles, { base: config.build.src, cwd: config.build.src })
// outputStyle This attribute is the default CSS built to be fully expanded, without closing braces at the end of the last attribute
.pipe(plugins.sass({ outputStyle: 'expanded' }))
.pipe(dest(config.build.temp))
.pipe(bs.reload({ stream: true}}))/ / js compilation
const script = () = > {
return src(config.build.paths.scripts, { base: config.build.src, cwd: config.build.src })
.pipe(plugins.babel({ presets: [require('@babel/preset-env')] }))
.pipe(dest(config.build.temp))
.pipe(bs.reload({ stream: true}}))/ / HTML compilation
const page = () = > {
return src(config.build.paths.pages, { base: config.build.src, cwd: config.build.src })
.pipe(plugins.swig({ data }))
.pipe(dest(config.build.temp))
.pipe(bs.reload({ stream: true}}))// Image compression
const image = () = > {
return src(config.build.paths.images, { base: config.build.src, cwd: config.build.src })
.pipe(plugins.imagemin())
.pipe(dest(config.build.dist))
}
// Compress the font file
const font = () = > {
return src(config.build.paths.fonts, { base: config.build.src, cwd: config.build.src })
.pipe(plugins.imagemin())
.pipe(dest(config.build.dist))
}
// Other path files compiled
const extra = () = > {
return src('* *', { base: config.build.public, cwd: config.build.public })
.pipe(dest(config.build.dist))
}
// Browser services
const serve = () = > {
// Listen for the corresponding file modification, and then execute the following task
watch(config.build.paths.styles, { cwd: config.build.src }, style)
watch(config.build.paths.scripts, { cwd: config.build.src }, script)
watch(config.build.paths.pages, { cwd: config.build.src }, page)
// bs.reload automatically refreshes the browser after listening for the corresponding file changes
watch([
config.build.paths.images,
config.build.paths.fonts
], { cwd: config.build.src }, bs.reload)
watch('* *', { cwd: config.build.public }, bs.reload)
bs.init({
notify: false.// Whether to display in the upper right corner
port: 8000.// Set the port to 3000 by default
// open: false, // Whether to automatically open the browser
// files: 'dist/**',
server: {
// As an array, the image font page is only used to compress the volume during construction
// Has no effect on the build test phase and only reduces the build efficiency
If there is no file in dist folder, look down SRC to improve build efficiency
// Build when it comes online
baseDir: [config.build.temp, config.build.src, config.build.public],
routes: {
'/node_modules' : 'node_modules'}}})}// File compression
const useref = () = > {
return src('temp/*.html', { base: config.build.temp })
.pipe(plugins.useref({ searchPath: ['. ', config.build.temp] }))
// html js css
.pipe(plugins.if(/\.js$/, plugins.uglify()))
.pipe(plugins.if(/\.css$/, plugins.cleanCss()))
.pipe(plugins.if(/\.html$/, plugins.htmlmin({
collapseWhitespace: true.minifyCSS: true.minifyJS: true
})))
.pipe(dest('dist'))}// Combine tasks
const compile = parallel(style, script, page)
const build = series(clean, parallel(series(compile, useref), image, font, extra))
const develop = series(build, serve)
// Export tasks to be executed
module.exports = {
clean,
develop,
compile,
build
}
Copy the code
The above is my basic understanding of automated construction, if there is any mistake, I hope you put forward, learn and progress together