Why NPM Scripts?
Originally published in 2016.2.12, the original address: https://css-tricks.com/why-npm-scripts/
Here is an article from a visitor Damon Bauer. The mood of the command-line interface, which has recently been directly used by the node package, continues to soar, whereas the enthusiasm for shielding abstract functionality by running tasks is gradually cooling. To a certain extent, you have to use NPM anyway, and NPM provides scripting, why not? But there are a number of reasons why we use NPM's scripting features. Damon will help us understand the reasons for this and tell us exactly how to accomplish most of the important tasks in the front-end building process in this way.
I have been using NPM scripts in my project for about half a year. Before that, I used gulp, before it was Grunt. Gulp and grunt are very easy to use, they do a lot of things that I need to do manually, and help me work faster. But I began to feel that I was spending more energy on these tools than I spent on my own code.
Grunt, Gulp, broccoli, brunch, and similar tools all need to configure their tasks to fit their paradigm and structure, and each of these tools needs to learn their different syntaxes, strange usages, and unique methods. This increases coding complexity, builds complexity, and lets you focus on fixing tools more than writing code.
because these build tools depending on the plug-in that wraps the core command-line tool, and further abstraction based on this core tool, this makes the error situation more complicated.
Here are three questions I have encountered several times:
- If the current command-line tool does not have the plugin you want to use, then you will be helpless (unless you write one yourself).
- The plugin you want to use wraps the old version of the tool, so the plug-in used and the current core tool's features and documentation do not match exactly the same.
- The error message is not friendly enough. If the plugin hangs, it's probably impossible to trace the error to the core tool, and I'm frustrated that I don't know how to debug the error.
However, please remember ...
If you are satisfied with your current build system, and it can do your best, please continue to use it! instead of using it blindly because NPM scripts is becoming more popular, focus on writing code rather than learning more tools. If you start to feel like you're fighting with the tools you use, then I suggest you consider using NPM scripts.
If you're making a decision now to investigate or use NPM scripts, continue reading this article! This article will provide a number of case tasks, and based on these tasks I have also created npm-build-boilerplate to facilitate your learning. So let's get started!
Write NPM Scripts
We'll spend a lot of time on the ' Package.json ' file. This file describes all of the dependencies and scripts that we need. Here is a section of my boilerplate project:
1 { 2 "name": "Npm-build-boilerplate", 3 "version": "1.0.0", 4 " Scripts ": { 5 ... 6 }, 7 " Devdependencies ": { 8 ... 9 }ten }
Next we'll step through the creation of the ' Package.json ' file. Our script is written to the scripts object, and all the tools we want to use will be installed and written to the Devdependencies object. Before you begin, the following are the project structures in this article:
Compiling scss as CSS
I am a heavy user of scss, usually work is dependent on scss. In order to compile scss into CSS, I used the node-sass. First, we need to install Node-sass and run the following code at the command line:
NPM Install--save-dev Node-sass
This command installs Node-sass in the current directory and is added to the Devdependencies object of ' Package.json '. It's handy when someone else is using your project, because they already have everything they need to run the project. once installed, run the following code at the command line when you use it:
Node-sass--output-style compressed-o dist/css src/scss
--output-style 标识,设置选项值为"compressed")。
Now that we know how to work at the command line, let's put it in NPM scirpt. Add the following to the ' Package.json ' scripts object:
"Scripts": { "scss": "Node-sass--output-style compressed-o dist/css src/scss"}
Now go back to the command line and run:
NPM Run Scss
You can see that the output of this run is consistent with the results obtained directly from the command line using the Node-sass command.
Any NPM script created in the remainder of this article can be run using the command line as in the previous example.
Just replace the task name you want to run from Scss with the name you want.
As you'll see, many of the command line tools we'll use has numerous options you can use with configure it exactly you SE E fit. For instance, here's the list of (Node-sass options). Here's a different setup show how to pass multiple options:
You'll see that many of the command-line tools we use have a lot of configuration items, and you can use configuration items to do exactly what you want to do. For example, this is a list of options for Node-sass, and the following shows how to configure multiple configuration items:
"Scripts": { "scss": "Node-sass--output-style nested--indent-type tab--indent-width 4-o dist/css Src/scs S "}
Use postcss to automatically prefix CSS
We've been able to compile scss into CSS, and now we want to automatically add a vendor prefix to the CSS code through autoprefixer and Postcss, and we can install multiple modules in a space-delimited way:
NPM Install--save-dev postcss-cli autoprefixer
Since POSTCSS does not do anything by default, we have installed two modules. POSTCSS relies on other plugins to handle the CSS you provide, such as autoprefixer.
After installing and saving the necessary tools to devdependencies, add a new task to your scripts object:
"Scripts": { ... " Autoprefixer ":" Postcss-u autoprefixer-r dist/css/* "}
This task means: Hi postcss, use the (-u identifier) autoprefixer replace (-r identifier) all the '. css ' files in the ' Dist/css ' directory to add the vendor prefix code to them. It's that simple! Want to modify the default browser prefix? Just add the following code to the script:
"Autoprefixer": "Postcss-u autoprefixer--autoprefixer.browsers ' > 5%, IE 9 '-R dist/css/* "
again, there are many options to configure your own build code:postcss-cli and Autoprefixer.
JavaScript Code Check
Maintaining standard formatting and styling is important for writing code, which ensures that errors are minimized and development efficiency is increased. "Code checking" helps us automate this work, so we use eslint to do code checking.
Once again, as described above, install the Eslint package, this time let's use the shortcut:
NPM i-d Eslint
This is the same effect as the following code:
NPM Install--save-dev Eslint
After the installation is complete, we configure some basic rules for eslint to run the code. Start a wizard with the following code:,
// Translator Note: The direct use here will be thrown wrong eslint can not find, because this method of use must be installed in the global, that is, through the NPM install i-g eslint mode installation
I recommend choosing "Answer code style questions" and answer questions about questions. In this process, Eslint will generate a new file in your project root directory and detect your related code.
Now, let's add the Code style detection task to the Scripts object of ' Package.json ':
"Scripts": { ... " Lint ":" Eslint src/js "}
Our mission is only 13 characters! It looks for all JavaScript files in the ' Src/js ' directory and checks for code based on the rules just generated. Of course, if you are interested, you can configure various rules in detail: Get crazy with theoptions
Confusing compressed JavaScript files
let's go ahead, we need to use uglify-js to confuse the compressed JavaScript file, first we need to install uglify-js:
NPM i-d Uglify-js
Then we can create a compressed hybrid task in ' Package.json ':
"Scripts": { ... " Uglify ":" Mkdir-p dist/js && uglifyjs src/js/*.js-m-o dist/js/app.js "}
The essence of NPM Scripts's task is the ability to repeat a command-line task shortcut (alias), which is one of the benefits of NPM scripts. This means you can use standard command line code directly in your script! This task uses two standard command line features: MkDir and &&.
The first part of the task " ": mkdir -p dist/js If the directory (-P ID) does not exist, create a directory structure (mkdir) and execute the UGLIFYJS command after successful creation. && helps you connect multiple commands and executes the remaining commands sequentially if the previous command succeeds.
The second part of the task tells Uglifyjs to all the JS files (' *.js ') in the ' src/js/' directory, using the "mangle" command (-m identifier) and outputting the results to the ' dist/js/app.js ' file. Here are the full configuration options for the UGLIFYJS tool list of options.
Let's update the Uglify task, create a compressed version of ' Dist/js/app.js ', link another uglifyjs command and pass the parameter to "compress" (-c identity).
"Scripts": { ... " Uglify ":" Mkdir-p dist/js && uglifyjs src/js/*.js-m-o dist/js/app.js && uglifyjs src/js/*.js-m-c-o D Ist/js/app.min.js "}
Compress pictures
below we will do the picture compression work. According to httparchive.org statistics, the network of the top 1000 site average page size of 1.9M, where the picture accounted for 1.1M (withimages accounting for 1.1MB of that Total). So one of the best ways to increase the speed of web pages is to reduce the size of the image.
Install IMAGEMIN-CLI:
NPM i-d IMAGEMIN-CLI
Imagemin is great, it can compress most image types, including Use the following code to compress an entire picture of a folder:
"Scripts": { ... " Imagemin ":" Imagemin src/images dist/images-p ",}
This task tells Imagemin to find and compress all the pictures in ' src/images ' and output to in ' dist/images '. The-p flag handles the image as a progressive image, if allowed. More configurations to view documents all available options
SVG wizard (Sprites)
the discussion about SVG has been getting hotter in recent years, and SVG has many advantages: it keeps loose structure on all devices, can be edited by CSS, and is friendly to reading screen software. However, SVG editing software often generates a lot of redundant code. Fortunately,svgo can help you automatically remove these redundant information (we'll install svgo soon).
Next we'll install svg-sprite-generator, which automatically processes and consolidates multiple SVG files into an SVG file (more processing options: More on thattechnique here).
NPM i-d svgo Svg-sprite-generator
You should now be familiar with the process-adding a task to your ' Package.json ' scripts object:
"Scripts": { ... " Icons ":" Svgo-f src/images/icons && mkdir-p dist/images && svg-sprite-generate-d src/images/icons-o di St/images/icons.svg "}
Note The icons task does three things with two && guides: 1. Use Svgo to pass an SVG directory (-f identifier), which compresses all SVG files in the directory; 2. If there is no ' dist/images ' The directory creates the directory (using the Mkdir-p command); 3. Using Svg-sprite-generator, pass in an SVG directory (-D identity) and the directory pathname of the output-processed SVG file (-o identification).
Provision of services through Browsersync, automatic monitoring and injection of changes
the last plugin is Browsersync, it can do the following things: Start a local service, automatically inject the updated files to the connected browser, and synchronize the browser's click and scroll. The code for installing and adding tasks is as follows:
NPM i-d browser-sync"Scripts": { ..." Serve ":" Browser-sync start--server--files ' dist/css/*.css, Dist/js/*.js ' "}
Browsersync task By default uses the path under the current root directory to start a server (--server identity),--files identity tells Browsersync to monitor the ' dist ' directory of CSS or JS files, once there is any change, the page is automatically injected with the changed files.
You can open multiple browsers at the same time (even on different devices), they will update the file changes in real-time!
Grouping tasks
Using the above tasks we can do the following functions:
- Compiling scss to CSS and automatically adding vendor prefixes
- Code checking and confusing compression of javascript
- Compress pictures
- Integrate SVG files in an entire folder into an SVG file
- Initiates a local service and automatically injects updates to the browser connected to the service.
This is not the whole content!
Merging CSS Tasks
Let's add a task that combines the both CSS related tasks (preprocessing Sass and running autoprefixer), so we don't have t o Run each one separately:
We will add a new task for merging two CSS related tasks (processing sass and performing prefixed Autoprefixer), and with this task we will not have to perform two related tasks separately:
"Scripts": { ... " Build:css ":" NPM run scss && npm run Autoprefixer "}
When you runnpm run build:css时,这个任务会告诉命令行去执行npm run scss,当这个任务成功完成后,会接着(&&)执行 npm run autoprefixer。
Just like this build:css task, we can link JavaScript tasks together to facilitate execution:
Merging JavaScript tasks
"Scripts": { ... " Build:js ":" NPM run lint && npm run Uglify "}
now, we can pass NPM Run Build:js is a one-step call for code detection and obfuscation of compressed JavaScript code!
Merge remaining tasks
For picture tasks, other remaining build tasks, we can turn them into a task in the same way:
"Scripts": { ... " Build:images ":" NPM run imagemin && npm run Icons ", " Build:all ":" NPM run build:css && npm ru N build:js && npm run Build:images ",}
Change monitoring
at this point, our task constantly needs to make some changes to the file, we constantly need to cut back to the command line to run the corresponding task. For this problem, we can add a task to listen for file changes, so that the files are automatically executed when the changes are made. Here I recommend using the onchange plug-in, the installation method is as follows :
NPM i-d onchange
Let's set up monitoring tasks for CSS and javascript:
"Scripts": { ... " Watch:css ":" OnChange ' src/scss/*.scss '--npm run Build:css ", " Watch:js ":" OnChange ' src/js/*.js '--npm ru N Build:js ",}
These tasks can be decomposed as follows: OnChange need you to pass the file path that you want to monitor (string), here we pass the Scss and JS source files, we want to run the command followed in-after, this command when the path of the file changes and additions will be immediately executed.
Let's add a monitoring command to complete our NPM scripts build process.
Add one more package, Parallelshell:
NPM i-d Parallelshell
Add a new task to the Scriopts object again:
"Scripts": { ... " Watch:all ":" Parallelshell ' npm run serve ' npm run Watch:css ' npm run Watch:js '}
parallelshell支持多个参数字符串,它会给npm run传多个任务用于执行。
Why is it that Parallelshell to merge multiple tasks instead of using && like previous tasks? I tried to do it at first, but the problem is that:&& links multiple commands to a piece and waits for each command to complete successfully before performing the next task. However, these commands never end when we run the Watch command! So we'll be stuck in an infinite loop.
therefore, using Parallelshell allows us to execute multiple watch commands at the same time. (Translator note: Later in the comments, it is recommended to use the Npm-run-all plug-in instead of Parallelshell, which supports this usage can be used to detect all watch tasks at once more convenient: "Watch": "Npm-run-all--parallel serve watch:* ")
This task uses the Browsersync NPM run serve task to start a service and then perform a monitoring command of the CSS and JavaScript files, once the CSS or JavaScript files have changed, The monitoring task executes the corresponding build task. Since Browsersync is set up to monitor changes in the ' dist ' directory, it will automatically inject new files into the associated URLs, which is great!
Other useful tasks
npm有大量可以实用的插件(ots of baked in tasks ),让我们再添加一个新的任务来看看这些插件对构建脚本的影响:
"Scripts": { ... " Postinstall ":" NPM Run Watch:all "}
当你在命令行中执行npm install的时候postinstall会立即执行,当团队合作时这个功能非常有用。当别人复制了你的项目并运行了npm install的时候,我们的watch:all任务就会马上执行,别人马上就会准备好一切开发环境:启动一个服务、打开一个浏览器窗口、监控文件变更。
Packaged
That's great! I hope you can learn some ways to use the NPM scripts build process and common command lines through this article.
In case you have forgotten something, I have created a npm-build-boilerplate project with all of the above mentioned tasks to facilitate your learning. If you have any questions or comments, please tweet me ( tweet at me) or leave a comment below and I will do my best to help you!
----Finished translating----
NPM scripts using the tutorial "translate"