NPM Scripts + Webpack hands-on experience (React, Nodejs)

Source: Internet
Author: User
Tags node server npm scripts postcss

Recently with WEBPACK+NPM Scripts+mongodb+nodejs+react wrote a background project, in the construction process with Webpack encountered a lot of pits, write to Share.

A variety of building tools, want to just learn Grunt,grunt was eliminated, replaced by gulp, its task flow mechanism, with logic clear, flexible and changeable characteristics, and easy to get started, compared to grunt really want to write too much configuration file code, immediately learn the wind water up, Just skilled gulp,webpack and such as the construction of a new star of the tool industry, its unique module packaging mechanism and a variety of easy-to-use loader, so that countless coder for it, together with the react,es6 of the perfect cooperation, Bo Master and immediately give up gulp, With a skeptical mind try to build a project purely with Webpack (note: Webpack and gulp are not conflicting, have been used in the project, but the blogger decided to try completely without Gulp is feasible), The result is certainly, gulp something (compression, merger, MD5) and so on , you can almost use Webpack to achieve it again, with NPM Scripts.

Let me start with a brief introduction to NPM Scripts. Take a look at the code First.

{"name": "app", "version": "0.0.1", "private": true, "main": "./bin/www", "scripts": {"clean": "rm-rf Client/di    st/* "," copy ":" rsync-a--exclude=*.html--exclude=*.jsx./client/src/*.*./client/dist "," start ":"./bin/www ", "server": "node server.js", "build": "npm run clean && webpack--config webpack.config.pro.js && npm ru N Copy && node qiniu.js "}," dependencies ": {" babel-runtime ":" ^6.11.6 "," body-parser ":" ~1.15.1 "," bo Otstrap-sass ":" ^3.3.7 "," classnames ":" ^2.2.5 "," cookie-parser ":" ~1.4.3 "," debug ":" ~2.2.0 "," ejs ":" ~2.4.1 " , "express": "~4.13.4", "mongoose": "^4.6.4", "morgan": "~1.7.0", "react": "^15.3.2", "react-dom": "^15.3.2 "," react-redux ":" ^4.4.5 "," react-router ":" ^2.8.1 "," redux ":" ^3.6.0 "," serve-favicon ":" ~2.3.0 "}," devde Pendencies ": {" autoprefixer ":" ^6.5.1 "," babel-core ":" ^6.17.0 "," babel-loader ":" ^6.2.5 "," Babel-plugin-tran Sform-runtime ":" ^6.15.0"," babel-preset-es2015 ":" ^6.16.0 "," babel-preset-react ":" ^6.16.0 "," css-loader ":" ^0.25.0 "," Cssnano ":" ^3. " 7.7 "," extract-text-webpack-plugin ":" ^1.0.1 "," file-loader ":" ^0.9.0 "," html-webpack-plugin ":" ^2.24.0 "," nod E-sass ":" ^3.10.1 "," postcss-loader ":" ^1.0.0 "," qiniu ":" ^6.1.13 "," react-hot-loader ":" ^3.0.0-beta.6 "," Sass -loader ":" ^4.0.2 "," style-loader ":" ^0.13.1 "," url-loader ":" ^0.5.7 "," webpack ":" ^1.13.2 "," webpack-dev-serv Er ":" ^1.16.2 "," webpack-md5-hash ":" 0.0.5 "}}

It is impossible for the front-end children's shoes not to touch this profile package.json, which is the important configuration file that NPM helps us manage, the scripts that is the way NPM scripts is used, the Key-value pairs that are configured in the scripts attribute of npm, You can use NPM run XXX "xxx as key name" to execute the corresponding values inside the command, such as: NPM run server, will execute node SERVER.JS,NPM scripts support Bash Shell. Is it a little familiar? You can configure multiple commands in a key name, connect through the && symbol, execute the first one, execute the second, and so on, until the last execution is finished, and if you want to execute concurrently, you can use a & symbol, but it seems that only bash support, You can do this in parallel using the Npm-run-all plugin or the Parallelshell plugin.

Too much nonsense, and then began to say webpack, have to talk nonsense, we used to gulp when the general will also configure two sets of task flow, development environment and production environment, Webpack of course can also do, but not like Gulp with the task of the way of free combination, instead, Write two configuration Files.

Webpack.config.pro.js

Webpack.config.dev.js

Let's first talk about the development environment, webpack.config.dev.js this configuration file. This configuration file uses Webpack-dev-server,webpack-dev-serve similar to gulp inside the browsersync, can create a front-end server, with code change monitoring, automatic refresh page, hot swap and other functions. Here I took the Webpack-dev-server configuration file separately, wrote a server.js, we can execute this file through node server.js, This file will create a dev server, and inject webpack.config.dev.js configuration to turn on the Server.

The Contentbase property is equivalent to the basedir inside the browsersync, which is the running file directory of a Server.

Hot This property is related to heat substitution, not to mention First.

var webpack = require (' webpack '), var webpackdevserver = require (' webpack-dev-server '); var config = require ('./ Webpack.config.dev '), new webpackdevserver (webpack (config), {  contentbase: ['./client/src '],  Stats: {    colors:true }, hot:true, Historyapifallback:true, headers: {' access-control-allow-origin ': ' * '} ). listen (3001, ' localhost ', function(err, result) {if (err) {return console.log (err)} Consol E.log (' Listening at http://localhost:3001/');});            

Let's look at the Webpack.config.dev.js file Again.

var path = require (' path 'var webpack = require (' webpack ')var autoprefixer = require (' autoprefixer ')var extracttextplugin = require (' extract-text-webpack-plugin ')); var source_dir = './client/src '; module.exports ={cache:true, context: __dirname, devtool: ' eval ', entry: {chores: [' webpack-dev-server/client?http://localhost:3001 '], business: [source_dir + '/router ', Source_dir + '/containers/app ', Source_dir + '/containers/homepage ', Source_dir + '/containers/taskpage ', Source_dir + '/containers/searchpage ', Source_dir + '/containers/listpage ', ' Webpack/hot/dev-server ']}, output: {path: '/', Filename: ' Scripts/[name].js '}, module: {loaders: [{test:/\.js[x]?$/, include:/client\/src/, Loader: ' Babel '}, {test:/\.scss$/, include:/(client\/src\/containers|client\/src\/components)/, loader:ExtractTextPlugin.extract (' style ', ' Css?modules&sourcemap&localidentname=[name]__[local]-[hash: Base64:5]!postcss!sass?outputstyle=expanded&sourcemap ', {publicpath: '/'})}, {test:/\.scss$/, include:/client\/src\/assets\/styles/, loader:ExtractTextPlugin.extract (' Style ', ' Css!postcss!sass?outputstyle=expanded&sourcemap ', {publicpath: '/' } '}, {//inline base64 URLs for & lt;=8k images, Direct URLs for the rest test:/\. (png|jpe?g|gif|svg) $/, loader: ' url?limit=8192&name=images/[name].[ Hash:8]. [ext] ' }, {test:/\. ( Eot|svg|ttf|woff) $/, loader: ' url?limit=8192&name=fonts/[name].[ Hash:8]. [ext] ' }]}, postcss:function  () {return  [autoprefixer ({browsers: [' last 2 versions ' ]})]; Plugins: [new  Webpack. Hotmodulereplacementplugin (), New  Webpack. Noerrorsplugin (), New Extracttextplugin (' styles/main.css ' , {allchunks:true }), new  Webpack.optimize.DedupePlugin ()], resolve: {extensions: [', '. js ', '. jsx ' ]}};     

A little crazy? It's okay, we're One by One.

The context of this property is the contextual environment of the configuration file, and we can use Node's __dirname.

Devtool is used to configure what kind of Sourcemap to use, here I will not say more, look at the official Documents.

webpack-dev-server/client?http://localhost:3001, What is the purpose of introducing this? This is to enable the server Auto-refresh must add the module, of course you can also use--inline mode, but the API mode does not support inline mode, so you have to add this module to all of your business logic Files. So your code changes, what do you find? Did you refresh it automatically? haha, huh!

With automatic refresh, not yet satisfied, we want hot replacement, what is hot replacement? In the case of not refreshing the page, changing the code will automatically change the page corresponding Content. Significant savings in development time (although This feature is still in beta). I'll use it with react hot loader here.

  Here comes the first pit , in the new version of hot loader inside, If you put Hot-loader in front of babel-loader, there will be an error, Module build failed:the Webpack Loader is now exported separately. if your loader is an unstable version, I recommend creating a new. BABELRC File.  

{"  presets": ["react", "es2015"],  "plugins": ["react-hot-loader/babel", "transform-runtime"]} 

Then in the file as above configuration, in addition to this configuration, you also need to add the following configuration:

    1. webpack/hot/dev-server, add to your business logic JS file, There is a second pit, if you pack multiple entrances, you need to add a webpack/hot/dev-server at each entrance, otherwise it will not Work.
    2. Add the new Webpack to the plugins module. Hotmodulereplacementplugin ()
    3. and set the Hot property to true in the previous server.js

Here I enclose an official troubleshooting Link.

Https://github.com/gaearon/react-hot-loader/blob/master/docs/Troubleshooting.md

A lot of people know that output is used to specify the path of the module, path is used to specify the output file directory, Publicpath is mainly for many plug-ins to provide the path, such as the replacement of static resource path, in the development environment we do not use, can not be configured, filename is the output file name, there's a third hole here, and filename doesn't just specify the file name, but it can also add a path, but it will be the Path's subpath, and the output path will be the context of all plug-ins.

  As for the other loader in the configuration file I will not tell each other, Children's shoes to study it.

How about the development environment is very simple? Then let's configure the production environment, the production environment is nothing more than some compilation process.

  Here's a place to pay attention, a lot of gulp to use the Webpack to the novice will have a problem, the development environment where we compiled the file? In the past, we used gulp to generate A. tmp temp folder, but Webpack seems like you're looking for a place to find it. In fact, Webpack to you in memory, you will not find these files on the disk, if you want to view these files, you can enter a path like the following in the Browser.

Http://localhost:3001/webpack-dev-server

So you can see the compiled Files.

  In the production environment we need to compress js, very simple:

New webpack.optimize.UglifyJsPlugin ({      mangle:true,      sourcemap:true,      compress: {        Warnings:false      }    })   

Extracttextplugin is used to export sass, less, CSS files separately, here is not much introduced, but there is a pit, note the following line of code Publicpath:

Extracttextplugin.extract (' style ', ' Css!postcss!sass?outputstyle=expanded&sourcemap ', {publicPath:config.qn_ access.origin}), be sure to set up, otherwise the problem occurs when replacing the picture MD5 path, and if it inherits the path of the CSS export, it will appear http://localhost:3001/styles/images/xxx. [md5].png This situation causes the image to be inaccessible.

  In addition Autoprefixer,url-loader these I do not introduce, gulp can do, Webpack more.

Finally change the file MD5 code the same problem, here cite an article.

Http://www.cnblogs.com/ihardcoder/p/5623411.html

After reading I believe you understand, with Webpackmd5hash This plug-in, the problem is properly solved.

finally, If you want to replace the CSS and JS reference paths in static html, you can use the Htmlwebpackplugin plugin as well as the compression Function. Attach the configuration file of the production Environment.

var path = require (' path 'var webpack = require (' webpack ')var autoprefixer = require (' autoprefixer ')var extracttextplugin = require (' extract-text-webpack-plugin ')var Webpackmd5hash = require (' webpack-md5-hash ')var htmlwebpackplugin = require (' html-webpack-plugin ')); var source_dir = './client/src 'var config = require ('./config ')); Module.exports ={cache:true, context: __dirname, devtool: ' Cheap-module-eval-source-map ', entry: {business: [source_dir + '/router ', Source_dir + '/containers/app ', Source_dir + '/containers/homepage ', Source_dir + '/containers/taskpage ', Source_dir + '/containers/searchpage ', Source_dir + '/containers/listpage ']}, output: {path: ' client/dist ', publicPath:config.qn_access.origin, filename: ' scripts/[name]. [chunkhash:8].js '}, module: {loaders: [{test:/\.js[x]?$/, include:/client\/src/, Loader: ' Babel '}, {test:/\.scss$/, include:/(client\/src\/containers|client\/src\/components)/, loader:ExtractTextPlugin.extract (' style ', ' Css?modules&sourcemap&localidentname=[name]__[local]-[hash: Base64:5]!postcss!sass?outputstyle=expanded&sourcemap '{publicPath:config.qn_access.origin})}, {test:/\.scss$/, include:/client\/src\/assets\/styles/, loader:ExtractTextPlugin.extract (' style ', ' Css!postcss!sass?outputstyle=expanded&sourcemap '{publicPath:config.qn_access.origin})}, {//inline base64 URLs for <=8k images, Direct URLs for the rest test:/ \. (png|jpe?g|gif|svg) $/, Loader: ' url?limit=8192&name=/images/[name]. [hash:8]. [ext] ' }, {test:/\. ( Eot|svg|ttf|woff) $/, Loader: ' url?limit=8192&name=/fonts/[name].[ Hash:8]. [ext] '} ]}, postcss:function() {return [autoprefixer ({browsers: [' last 2 versions ']});}, plugins: [new Extracttextplugin (' styles/main.[ Contenthash:8].css ', {allchunks:true }), new webpack.optimize.DedupePlugin (), new  Webpack.optimize.UglifyJsPlugin ({mangle:true, Sourcemap:true, compress: {warnings:false }}), new
                                             
                                               Webpackmd5hash (), new
                                               htmlwebpackplugin ({title: ' xxx ', template: ' client/src/template.html ' }), Resolve: {extensions: [', '. js ', '. jsx '}};    
                                                    

Conclusion: have to sigh, JS design defects instead led to the vigorous development of the ecological environment, there are always great God to write some practical plug-ins to solve some language or frame pain points, hope that the front end of the circle more and more good, thank you!

NPM Scripts + webpack hands-on experience (React, Nodejs)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.